1 条题解

  • 0
    @ 2025-5-28 10:40:46

    这个问题需要我们高效地存储多个规范排序的牌组链表,通过共享公共尾节点来减少内存使用。核心思路是利用字典树(Trie)的结构特性来实现节点共享。

    核心数据结构与设计思路

    1. 字典树(Trie)

      • 使用二维数组aa表示字典树,其中a[e][q]表示节点ee的子节点qq
      • 每个节点代表一张牌,路径表示牌组
    2. 牌的编码

      • 将每张牌编码为0510-51之间的唯一整数
      • 点数AKA-K映射为0120-12,花色CDHSC、D、H、S分别映射为01326390、13、26、39
      • 最终编码为点数+花色偏移量点数 + 花色偏移量
    3. 逆向插入

      • 由于需要共享尾节点,每次插入牌组时逆序处理牌,使得字典树的深度方向对应链表的尾部到头部

    核心算法解析

    1. 字典树构建

      • 初始化根节点为11
      • 对于每个牌组,逆序处理每张牌,插入到字典树中
      • 如果节点不存在,则创建新节点,否则复用现有节点
    2. 节点计数

      • 字典树中的节点总数即为所需链表节点数
      • 由于根节点不代表实际牌,最终结果为总节点数减11

    代码实现

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    int ans=0,p,n;
    int a[100000][100];
    char s[400000];
    int q[300000],c[100000],w[100000],g[100000];
    void lily(){//字典树建树
    	int e=1;
    	for(int i=0;i<n;i++){
    		if(a[e][q[i]]==0)
    			a[e][q[i]]=++p;
    		e=a[e][q[i]];
    	}
    }
    int main(void){
    	int i,j,k,m,t;
    	for(i=2;i<=9;i++)
    		w[i+'0']=i-1;
    	w['A']=0;w['J']=10;w['Q']=11;w['K']=12;
    	g['c']=0;g['D']=13;g['H']=26;g['S']=39;
    	while(scanf("%d",&t)==1&&t){
    		memset(a,0,sizeof(a));//清空
    		p=1;
    		while(t--){
    			scanf("%d",&n);
    			for(i=0;i<n;i++){
    				scanf("%s",s);
    				if(s[0]=='1'&&s[1]=='0')//统计
    					q[n-i-1]=9+g[s[2]];
    				else
    					q[n-i-1]=w[s[0]]+g[s[1]];
    			}
    			lily();
    			for(i=0;i<n;i++)q[i]=0;//清空
    		}
    		printf("%d\n",p-1);//输出
    	}
    	return 0;
    }
    
    

    复杂度分析

    • 时间复杂度:O(N),其中N为所有牌组中的牌总数
    • 空间复杂度:O(N),主要用于存储字典树

    注意事项

    1. 输入处理

      • 正确处理牌的编码,特别是10的特殊情况
      • 逆序处理牌组以共享尾节点
    2. 内存管理

      • 使用二维数组表示字典树,适用于节点数不超过100,000的情况
      • 每次测试用例后需要重置字典树
    3. 结果输出

      • 节点数需排除根节点,因此结果为总节点数减1
    • 1

    信息

    ID
    2284
    时间
    2000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者