UVA1673 str2int(SAM)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVA1673 str2int(SAM)相关的知识,希望对你有一定的参考价值。

 

【题目链接】

 

    http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=51267

 

【题意】

 

    给定n个字符串,计算所有忽略前导0的子串形成的不重整数之和。

 

【思路】

 

    既然是处理子串问题,我们可以合并串之后构造一个SAM。

    SAM的性质:结点u代表的字符串集是从根到u路径上的所有结点代表的字符串集之并,结点u所代表的字符串集为最长串的所有子串。

    记cnt[u]为状态u代表的字符串个数,sum[u]代表状态u代表的字符串对应的数之和。

    拓扑排序后,设p为当前结点,trans(p,j)为np,则有:

        cnt[np]+=cnt[p]

       sum[np]+=sum[p]*10+cnt[p]*j

 

    不走$边,第一次不走0边。

 

【代码】

 

 1 #include<set>
 2 #include<cmath>
 3 #include<queue>
 4 #include<vector>
 5 #include<cstdio>
 6 #include<cstring>
 7 #include<iostream>
 8 #include<algorithm>
 9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
10 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
11 using namespace std;
12 
13 typedef long long ll;
14 const int N = 2e5+10;
15 const int MOD = 2012;
16 
17 int n,len;
18 char s[N];
19 int sum[N],cnt[N];
20 int sz,last,fa[N],ch[N][11],l[N],c[N],b[N];
21 
22 void add(int c)
23 {
24     int p=last,np=++sz; last=np;
25     l[np]=l[p]+1;
26     for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
27     if(!p) fa[np]=1;
28     else {
29         int q=ch[p][c];
30         if(l[q]==l[p]+1) fa[np]=q;
31         else {
32             int nq=++sz; l[nq]=l[p]+1;
33             memcpy(ch[nq],ch[q],sizeof(ch[q]));
34             fa[nq]=fa[q];
35             fa[q]=fa[np]=nq;
36             for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq; 
37         }
38     }
39 }
40 void init()
41 {
42     sz=last=1;
43     len=0;
44     memset(sum,0,sizeof(sum));
45     memset(cnt,0,sizeof(cnt));
46     memset(ch,0,sizeof(ch));
47     memset(c,0,sizeof(c));
48     memset(fa,0,sizeof(fa));
49     memset(l,0,sizeof(l));
50 }
51 int main()
52 {
53     while(scanf("%d",&n)==1) 
54     {
55         init();
56         FOR(i,1,n) {
57             scanf("%s",s);
58             if(i!=1) add(10),len++;
59             for(int j=0;s[j];j++)
60                 add(s[j]-0),len++;
61         }
62         FOR(i,1,sz) c[l[i]]++;
63         FOR(i,1,len) c[i]+=c[i-1];
64         FOR(i,1,sz) b[c[l[i]]--]=i; 
65     
66         int ans=0;
67         cnt[1]=1;
68         FOR(i,1,sz) {
69             int p=b[i];
70             for(int j=0;j<10;j++) {
71                 if(i==1&&j==0) continue;
72                 if(ch[p][j]) {
73                     int np=ch[p][j];
74                     cnt[np]=(cnt[np]+cnt[p])%MOD;
75                     sum[np]=(sum[np]+sum[p]*10+cnt[p]*j)%MOD;
76                 }
77             }
78             ans=(ans+sum[p])%MOD;
79         }
80         printf("%d\n",ans);
81     }
82     return 0;
83 }

 

以上是关于UVA1673 str2int(SAM)的主要内容,如果未能解决你的问题,请参考以下文章

HDU 4436 str2int (广义SAM)

Uva 11419 我是SAM

UVa 11419 我是SAM(最小点覆盖+路径输出)

题解 UVA11419 SAM I AM

uva 11419 SAM I AM

UVa 11419 SAM I AM (最小覆盖数)