HDU 4436 str2int(后缀数组,一种统计n个digit字符串所有不同子串之和的方法)
来源:互联网 发布:初学者学linux 编辑:程序博客网 时间:2024/06/01 08:11
str2int
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1448 Accepted Submission(s): 500
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.
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.
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
510112309000 1234567890
Sample Output
202
Source
2012 Asia Tianjin Regional Contest
Recommend
zhoujiaqi2010 | We have carefully selected several similar problems for you: 5107 5106 5105 5104 5103
用后缀数组处理,但是最后统计答案的办法需要深入思考,不过也不难。
目前先不写题解了,以后我时间总结一个后缀数组的所有类型题目。
//Hello. I'm Peter.#include<cstdio>#include<iostream>#include<sstream>#include<cstring>#include<string>#include<cmath>#include<cstdlib>#include<algorithm>#include<functional>#include<cctype>#include<ctime>#include<stack>#include<queue>#include<vector>#include<set>#include<map>using namespace std;typedef long long ll;typedef long double ld;#define peter cout<<"i am peter"<<endl#define input freopen("data.txt","r",stdin)#define randin srand((unsigned int)time(NULL))#define INT (0x3f3f3f3f)*2#define LL (0x3f3f3f3f3f3f3f3f)*2#define gsize(a) (int)a.size()#define len(a) (int)strlen(a)#define slen(s) (int)s.length()#define pb(a) push_back(a)#define clr(a) memset(a,0,sizeof(a))#define clr_minus1(a) memset(a,-1,sizeof(a))#define clr_INT(a) memset(a,INT,sizeof(a))#define clr_true(a) memset(a,true,sizeof(a))#define clr_false(a) memset(a,false,sizeof(a))#define clr_queue(q) while(!q.empty()) q.pop()#define clr_stack(s) while(!s.empty()) s.pop()#define rep(i, a, b) for (int i = a; i < b; i++)#define dep(i, a, b) for (int i = a; i > b; i--)#define repin(i, a, b) for (int i = a; i <= b; i++)#define depin(i, a, b) for (int i = a; i >= b; i--)#define pi 3.1415926535898#define eps 1e-6#define MOD 2012#define MAXN 200100#define N MAXN-10#define Mint wa[MAXN],wb[MAXN],wv[MAXN],wss[MAXN],sa[MAXN],r[MAXN];int cmp(int *r,int a,int b,int l){ return r[a]==r[b] && r[a+l]==r[b+l];}void Build_SuffixArray(int *r,int *sa,int n,int m){ int i,j,p,*x=wa,*y=wb,*t; rep(i,0,m) wss[i]=0; rep(i,0,n) wss[x[i]=r[i]]+=1; rep(i,1,m) wss[i]+=wss[i-1]; depin(i,n-1,0) sa[--wss[x[i]]]=i; for(j=1,p=1;p<n;j*=2,m=p){ for(p=0,i=n-j;i<n;i++) y[p++]=i; rep(i,0,n) if(sa[i]>=j) y[p++]=sa[i]-j; rep(i,0,n) wv[i]=x[y[i]]; rep(i,0,m) wss[i]=0; rep(i,0,n) wss[wv[i]]+=1; rep(i,1,m) wss[i]+=wss[i-1]; depin(i,n-1,0) sa[--wss[wv[i]]]=y[i]; for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; }}int ranking[MAXN],height[MAXN];void Build_heightArray(int *r,int *sa,int n){ int i,j,k=0; repin(i,1,n) ranking[sa[i]]=i; for(i=0;i<n;height[ranking[i++]]=k){ for(k?k--:0,j=sa[ranking[i]-1];r[i+k]==r[j+k];k++); }}int idx(char c){ return c-'0';}int tenpow[MAXN],tenpowsum[MAXN],symbol[MAXN],preans[MAXN],preanssum[MAXN],lenlimit[MAXN];int n,lens,numsym,ans;char s[MAXN];bool leggal(int i){//符合题意当且仅当 公共前缀长度不为0 且 s[i]处字符为'1'-'9'之间; if(!height[i]) return false; int p=sa[i]; if(!isdigit(s[p])) return false; int t=idx(s[p]); if(!t) return false; else return true;}int Get_Number(char *s,int from,int to){//给定一个数字字符串S,O(1)求出从给定的S[L]..S[R]部分的所有前缀数字之和 int lent=to-from+1; int res=preanssum[to]-preanssum[from-1]; res=(res%MOD+MOD)%MOD; res-=preans[from-1]*(tenpowsum[lent]-1); return res;}int main(){ //预处理y1(x)=10^x数组 以及 y1数组的前缀和数组 tenpow[0]=1; repin(i,1,N){ tenpow[i]=tenpow[i-1]*10; tenpow[i]%=MOD; } tenpowsum[0]=1; repin(i,1,N){ tenpowsum[i]=tenpowsum[i-1]+tenpow[i]; tenpowsum[i]%=MOD; } while(~scanf("%d",&n)) { //构造字符串: s[0]='#'; lens=1; numsym=0; symbol[++numsym]=0; repin(i,1,n){ scanf("%s",s+lens); int lent=len(s+lens); lens+=lent; symbol[++numsym]=lens; s[lens++]='#'; } s[lens]='\0'; ans=0; //构造每个串的长度限制数组: depin(i,lens-1,0){ if(s[i]=='#') lenlimit[i]=0; else{ lenlimit[i]=lenlimit[i+1]+1; } } //构造每个串的前缀答案以及前缀和答案 repin(i,1,numsym-1){ preans[symbol[i]]=preans[symbol[i+1]]=0; preanssum[symbol[i]]=preanssum[symbol[i+1]]=0; int last=0,now=0; rep(j,symbol[i]+1,symbol[i+1]){ now=last*10+idx(s[j]); now%=MOD; preans[j]=now; preanssum[j]=preanssum[j-1]+now; preanssum[j]%=MOD; last=now; } //统计所有无前导0的数之和,记为ans (以后再减去多余部分) rep(j,symbol[i]+1,symbol[i+1]){ if(!idx(s[j])) continue; ans+=Get_Number(s,j,symbol[i+1]-1); ans%=MOD; } } //构造后缀数组和height数组 rep(i,0,lens){ r[i]=static_cast<int>(s[i]); } r[lens]=0; Build_SuffixArray(r,sa,lens+1,'9'+1); Build_heightArray(r,sa,lens); //用后缀和height数组的性质将ans减去ans中多余的部分 repin(i,1,lens){ if(!leggal(i)) continue; int from=sa[i]; int lent=min(height[i],lenlimit[from]); int to=from+lent-1; ans-=Get_Number(s,from,to); ans=(ans%MOD+MOD)%MOD; } printf("%d\n",ans); }}
0 0
- HDU 4436 str2int(后缀数组,一种统计n个digit字符串所有不同子串之和的方法)
- hdu 4436 str2int 后缀数组
- hdu 4436 str2int ( 后缀数组 )
- HDU 4436 str2int 后缀数组 字符串哈希 前缀和
- hdu 4436 str2int 后缀数组、后缀自动机
- [后缀数组+思路] hdu 4436 str2int
- hdu 4436 str2int(后缀数组)
- New Distinct Substrings (后缀数组,统计有多少个不同的子串)
- hdu 3948 后缀数组统计不同回文串的个数
- 有多少个不同的子串?-- 后缀数组
- hdu 4436 str2int (后缀自动机)
- HDU 4436 str2int【后缀自动机】
- Hdu 4436 str2int 后缀自动机
- HDU 4436 str2int 后缀数组(前缀和预处理)
- hdu 5769后缀数组 求含有某个字母的某个字符串的不同子串的个数
- hdu3948——后缀数组统计不同回文子串的个数
- spoj694 Distinct Substrings(后缀数组+统计不同子串的个数)
- HDU 4436 str2int (后缀自动机SAM,多串建立)
- 深度剖析C++虚函数
- 作为程序员应该知道的九句话
- UVa - 445 - Marvelous Mazes(AC)
- SQL语言学习小结(一)
- BOM 输入物料反查函数(待测试) CS15功能类似
- HDU 4436 str2int(后缀数组,一种统计n个digit字符串所有不同子串之和的方法)
- struts2的配置文件global-results
- 让sles10支持多处理器
- 第十二周项目三 用递归方法求解(2)求1*3*...*n的递归式
- Java操作LDAP的基本方法
- 第12周项目递归函数返回fib(20)
- Unity3D技术之从 Maya 中导入对象浅析
- web版用户通过浏览器下载图片java后台代码
- 聚合函数与group by问题