LCP Array
Accepts: 131
Submissions: 1352
Time Limit: 4000/2000 MS (Java/Others)
Memory Limit: 131072/131072 K (Java/Others)
问题描述
Peter有一个字符串s=s1s2...sn, 令suffi=sisi+1...sn是s第i字符开头的后缀. Peter知道任意两个相邻的后缀的最长公共前缀ai=lcp(suffi,suffi+1)(1≤i<n). 现在给你数组a, Peter有多少个仅包含小写字母的字符串满足这个数组. 答案也许会很大, 你只要输出对109+7取模的结果即可.
输入描述
输入包含多组数据. 第一行有一个整数T, 表示测试数据的组数. 对于每组数据: 第一行包含一个整数n (2≤n≤105)表示字符串的长度. 第二行包含n−1个整数: a1,a2,...,an−1 (0≤ai≤n). 所有数据中n的和不超过106.
输出描述
对于每组数据, 输出答案对109+7取模的结果.
输入样例
3 3 0 0 4 3 2 1 3 1 2
输出样例
16250 26 0
思路:
LCP Array
如果ai=x, 那么可以推断出si=si+1=...=si+x, 并且如果ai≠0, 那么ai+1=ai−1, 利用第二个条件判断无解, 利用第一个条件划分等价类. 假设有m个等价类, 那么答案就是26⋅25m−1
第一题就花了一个多钟才A真的是有毒,漏了个k>n-i还Wa了。。。。。
AC代码:
#include<iostream> #include<functional> #include<algorithm> #include<cstring> #include<string> #include<vector> #include<cstdio> #include<cmath> #include<map> using namespace std; #define CRL(a) memset(a,0,sizeof(a)) #define QWQ ios::sync_with_stdio(0) typedef unsigned long long LL; typedef long long ll; #define CMP bool cmp(const node& a,const node& b){ return a.R<b.R||(a.R==b.R&&a.L<b.L); } const int T = 100000+50; const int mod = 1000000007; int main() { #ifdef zsc freopen("input.txt","r",stdin); #endif int i,k,n,t,cnt,cur,c; scanf("%d",&t); while(t--) { cnt = cur = 0; scanf("%d",&n); bool f1; f1 = false; c = 0; for(i=1;i<n;++i){ scanf("%d",&k); if(cur&&cur-k!=1||k>n-i)f1 = true;//不是1,0的情况 if(cur&&!k)c++;//1,0的情况 else if(k==0)cnt++;//0,0的情况 cur = k;//保存上一次的值 } if(f1){ printf("0\n"); } else if(c+1==n&&!cnt){ printf("26\n"); } else { ll sum = 26; for(i=1;i<=c+cnt;++i){ sum = sum*25%mod; } printf("%I64d\n",sum); } } return 0; }