字符串(多串后缀自动机):HDU 4436 str2int

str2int

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 2082    Accepted Submission(s): 744

Problem Description

In this problem, you are given several strings that contain only digits from ‘0‘ to ‘9‘, inclusive.
An example is shown below.
101
123
The set S of strings is consists of the N strings given in the input file, and all the possible substrings of each one of them.
It‘s boring to manipulate strings, so you decide to convert strings in S into integers.
You
can convert a string that contains only digits into a decimal integer,
for example, you can convert "101" into 101, "01" into 1, et al.
If an integer occurs multiple times, you only keep one of them.
For example, in the example shown above, all the integers are 1, 10, 101, 2, 3, 12, 23, 123.
Your task is to calculate the remainder of the sum of all the integers you get divided by 2012.

Input

There are no more than 20 test cases.
The test case starts by a line contains an positive integer N.
Next N lines each contains a string consists of one or more digits.
It‘s guaranteed that 1≤N≤10000 and the sum of the length of all the strings ≤100000.
The input is terminated by EOF.

Output

An integer between 0 and 2011, inclusive, for each test case.

Sample Input

5

101

123

09

000

1234567890

Sample Output

202

  这道题用后缀自动机可以很好地解决。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 const int mod=2012;
 6 const int maxn=200010;
 7 int cnt,last,n,ans,sum[maxn];
 8 int wv[maxn],sa[maxn],tot[maxn];
 9 int ch[maxn][12],fa[maxn],len[maxn];
10 struct SAM{
11     void Init(){
12         memset(ch,0,sizeof(ch));
13         memset(fa,0,sizeof(fa));
14         memset(len,0,sizeof(len));
15         last=cnt=1;
16     }
17     void Insert(int c){
18         int p=last,np=last=++cnt;len[np]=len[p]+1;
19         while(p&&!ch[p][c])ch[p][c]=np,p=fa[p];
20         if(!p)fa[np]=1;
21         else{
22             int q=ch[p][c];
23             if(len[p]+1==len[q])
24                 fa[np]=q;
25             else{
26                 int nq=++cnt;len[nq]=len[p]+1;
27                 memcpy(ch[nq],ch[q],sizeof(ch[q]));
28                 fa[nq]=fa[q];fa[q]=fa[np]=nq;
29                 while(p&&ch[p][c]==q)
30                     ch[p][c]=nq,p=fa[p];
31             }
32         }
33     }
34
35     void Extend(char *s){
36         int l=strlen(s);last=1;
37         for(int i=0,c;i<l;i++){
38             c=s[i]-‘0‘;
39             if(!ch[last][c]||len[ch[last][c]]!=i+1)
40                 Insert(c);
41             else
42                 last=ch[last][c];
43         }
44     }
45 }sam;
46
47 char s[maxn];
48
49 int main(){
50     while(scanf("%d",&n)!=EOF){
51         sam.Init();
52         for(int i=1;i<=n;i++)
53             scanf("%s",s),sam.Extend(s);
54
55         memset(wv,0,sizeof(wv));
56         memset(sa,0,sizeof(sa));
57         for(int i=1;i<=cnt;i++)
58             wv[len[i]]++;
59         for(int i=1;i<=cnt;i++)
60             wv[i]+=wv[i-1];
61         for(int i=cnt;i>=1;i--)
62             sa[--wv[len[i]]]=i;
63         memset(tot,0,sizeof(tot));
64         memset(sum,0,sizeof(sum));
65         tot[1]=1;ans=0;
66         for(int i=0;i<cnt;i++){
67             int x=sa[i];
68             for(int j=0;j<=9;j++){
69                 if(x==1&&j==0)continue;
70                 (tot[ch[x][j]]+=tot[x])%=mod;
71                 (sum[ch[x][j]]+=(sum[x]*10+tot[x]*j))%=mod;
72             }
73             (ans+=sum[x])%=mod;
74         }
75         printf("%d\n",ans);
76     }
77 }
时间: 2024-10-29 19:12:04

字符串(多串后缀自动机):HDU 4436 str2int的相关文章

hdu 4436 str2int(后缀自动机)

题目链接:hdu 4436 str2int 题意: 给你n个字符串,每个字符串都是由数字构成,现在让你将这n个字符串所有的不重复子串构成的十进制数字加起来mod2012. 题解: 似乎这种不重复的子串问题,用后缀自动机都比较无脑搞. 首先将所有的串连起来,中间插个特殊字符,然后建立后缀自动机. 然后拓扑排序,从跟开始往下dp. sum[v]=Σ(sum[x]*10+cnt[x]*j),其中cnt[x]表示有多少条路径能到x这个节点,转移为cnt[v]=Σcnt[x] (x能转移到v),j为这个节

HDU 4436 str2int

str2int Time Limit: 3000ms Memory Limit: 131072KB This problem will be judged on HDU. Original ID: 443664-bit integer IO format: %I64d      Java class name: Main In this problem, you are given several strings that contain only digits from '0' to '9',

51nod1469 淋漓字符串(后缀自动机)

题目大意: 首先,我们来定义一下淋漓尽致子串. 1.令原串为S. 2.设子串的长度为len,在原串S中出现的次数为k,令其出现的位置为p1, p2, ....pk(即这个子串在原串中[pi,pi + len - 1]中出现). 3.若k=1,则该子串不是淋漓尽致子串. 4.若存在pi,pj(i != j),使得S[pi - 1] = S[pj - 1],则该子串不是淋漓尽致子串. 5.若存在pi,pj(i != j),使得S[pi + len] = S[pj + len],则该字串不是淋漓尽致字

HDU 4436 str2int(后缀自动机)

[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=4436 [题目大意] 给出一些字符串,由0~9组成,求出所有不同子串的和. [题解] 将所有字符串添加拼接符10连接在一起建立自动机, 从起点开始遍历所有节点,就能计算所有的子串和了.注意转移的时候只转移0到9节点. [代码] #include <cstdio> #include <cstring> #include <algorithm> #include <ve

字符串(后缀自动机):HDU 4622 Reincarnation

Reincarnation Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 3194    Accepted Submission(s): 1184 Problem Description Now you are back,and have a task to do: Given you a string s consist of lo

字符串(后缀自动机):Ahoi2013 差异

Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sample Output 54 HINT 2<=N<=500000,S由小写英文字母组成 建反向前缀树,O(N)dp求解. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 const int N=

字符串(后缀自动机):NOI 2016 优秀的拆分

[问题描述] 如果一个字符串可以被拆分为 AABB 的形式,其中 A 和 B 是任意非空字符串, 则我们称该字符串的这种拆分是优秀的. 例如,对于字符串 aabaabaa,如果令 A = aab, B = a, 我们就找到了这个字符串拆分成 AABB 的一种方式. 一个字符串可能没有优秀的拆分,也可能存在不止一种优秀的拆分. 比如我们令 A = a, B = baa,也可以用 AABB 表示出上述字符串:但是,字符串abaabaa 就没有优秀的拆分. 现在给出一个长度为 n 的字符串 S,我们需

字符串(后缀自动机):COGS 2399. 循环同构

这道题直接看代码吧. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 const int maxn=2000010; 6 int fa[maxn],len[maxn],rit[maxn],w[maxn],sa[maxn]; 7 int n,Q,cnt,lst,ch[maxn][26],vis[maxn]; 8 char s[maxn]; 9 s

后缀自动机(SAM)学习指南

*在学习后缀自动机之前需要熟练掌握WA自动机.RE自动机与TLE自动机* 什么是后缀自动机 后缀自动机 Suffix Automaton (SAM) 是一个用 O(n) 的复杂度构造,能够接受一个字符串所有后缀的自动机. 它最早在陈立杰的 2012 年 noi 冬令营讲稿中提到. 在2013年的一场多校联合训练中,陈立杰出的 hdu 4622 可以用 SAM 轻松水过,由此 SAM 流行了起来. 一般来说,能用后缀自动机解决的问题都可以用后缀数组解决.但是后缀自动机也拥有自己的优点. 1812.