hdu 3336
2015-09-14 19:58
162 查看
<span style="background-color: rgb(0, 153, 0);">/*题意:就是让给你一个字符串,然后计算不断增加的前缀字符串在整个字符创当中出现的次数和,可能出现的次数过大,所以要求结果1007. 例如:abab a 2 ab 2 aba 1 abab 1 2+2+1+1=6 */ /*思路:其实我们想想比如对于位置i来说,现在我们求出了f[i]的值,那么[0,f[i]-1]串就是一个 能匹配i-1位置的最长的前缀串。且我们根据f[i]的值可以定位其他所有可匹配的前缀。KMP的思想 就是找出每个位置i的可匹配最大前缀j。令dp[i]表示S[0,i-1]串的后缀能匹配的前缀个数, 那么dp[i]=dp[next[i]]+1, dp[1]=1正好表示串s[0]的后缀只能匹配串s[0]. */</span> #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<queue> #include<stack> #include<map> #include<set> #include<vector> using namespace std; typedef long long ll; typedef pair<int,int> pp; #define inf 0x3f3f3f3f #define eps 1e-10 #define maxl 200020 #define mem(i,j) memset(i,j,sizeof(i)) const int mod=10007; int f[maxl],d[maxl],len; char s[maxl]; void getnext(char *s,int *f){ f[0]=f[1]=0; for(int i=1;i<len;i++){ int j=f[i]; while(j&&am 4000 p;s[i]!=s[j]) j=f[j];//这里不断的替换来降低复杂度 f[i+1]=(s[i]==s[j])?j+1:0;//f[i+1]保存的是s[i]的前缀的长度 } } int main() { //freopen("in.txt", "r", stdin); int t; cin>>t; while(t--){ cin>>len>>s; getnext(s,f); memset(d,0,sizeof(d)); int ans=0; for(int i=1;i<=len;i++){ d[i]=d[f[i]]+1;//因为f[i]记录的是i-1的前缀的长度 但是不知道它的次数 后面的是在前面的结果上面累加的 所以每次加1 直到后面如果还是有相同的前缀的时候已经累加上去了 ans=(ans+d[i])%mod; } cout<<ans<<endl; } }
相关文章推荐
- linux文件管理命令
- 斐波那契博弈(转)
- JavaVM和JNIEnv
- 文件过滤驱动开发
- 【原】移动web资源整理
- DOM数据解析
- [置顶] android studio 查看源码时有些类显示 can not resolve 的问题
- SDWebImage的简单使用
- java中的SecureRandom在linux中的实现
- vlc 播放器的播放进度条的时间不刷新
- hdu 5437 Alisha’s Party (线段树)
- 【Linux命令详解】12、文本内容显示―[ cat、tac、more、less、tail、head]
- 黑马程序员-------C语言----文件读写
- 设计模式——代理模式(RMI初接触)
- XML数据解析可以直接调用此方法
- 第三周—项目2 建设“顺序表”算法库
- 取随机数不重复问题
- JAVA连接mysql
- Objective-C 【NSDictionary 文件操作(重点)&简写形式】
- C++内存管理