--------字符串--------
Icefox_zhx
这个作者很懒,什么都没留下…
展开
-
SPOJ694&SPOJ705(后缀数组)
这俩题一样。。就后者数据范围大些。题目:给定一个字符串,求不相同的子串的个数。每个子串一定是某个后缀的前缀,那么原问题等价于求所有后缀之间的不相同的前缀的个数。从1到n扫一遍,每一个suffix[sa[i]]的贡献为 n-sa[i]+1- height[i].(sa[i]的前缀个数-重复个数)#include #include #define N 50010int n,m,r原创 2017-07-17 16:26:55 · 548 阅读 · 0 评论 -
bzoj1031[JSOI2007]字符加密Cipher(拆环变链,利用sa数组)
挺裸的一道后缀数组。。注意是环,把他在后面复制一遍再做就好了。。#include #include #define N 200005char s[N];int n,rank[N<<1],st[256],rank1[N],count[N],sa[N],tmp[N];int main(){// freopen("a.in","r",stdin); scanf("%s",s+1原创 2017-07-17 16:32:14 · 382 阅读 · 0 评论 -
bzoj1717(poj3261) [Usaco2006 Dec]Milk Patterns 产奶的模式(后缀数组,二分答案)
给定一长度为N的数字序列,找出在序列中重复出现了至少K次的最长子串。二分答案。利用h数组判断即可。按h分组,连续大于等于x的分在一组,他们肯定有相同的前缀,统计次数即可。#include #include #include #define N 20005int n,m,a[N],aa[N];int rank[N<<1],count[N],rank1[N],sa[N],t原创 2017-07-17 16:35:51 · 403 阅读 · 0 评论 -
bzoj1692 [Usaco2007 Dec]队列变换(后缀数组)
DescriptionFJ打算带他的N(1 <= N <= 30,000)头奶牛去参加一年一度的“全美农场主大奖赛”。在这场比赛中,每个参赛者都必须让他的奶牛排成一列,然后领她们从裁判席前依次走过。 今年,竞赛委员会在接受队伍报名时,采用了一种新的登记规则:他们把所有队伍中奶牛名字的首字母取出,按它们对应奶牛在队伍中的次序排成一列(比如说,如果FJ带去的奶牛依次为Bessie、Sylv原创 2017-07-17 16:45:39 · 370 阅读 · 0 评论 -
ural1297Palindrome (后缀数组+lcp)
求最长回文子串,且此题要求最先出现,SA+lcp解决。原想法:首先反转,拼接原串与反转串,然后求两者的最长公共前缀,唯一注意的是如果有多组要输出最先出现那一组。原想法是错误的。反例:zzzdzaadzzz。可以自己摸索下,实在不行,来这位大神博客下拜读一下也是可以的。传送门正解:首先要在本身与镜像之间插入一个特殊的,不可能出现的字符。我们枚举每一个原始字符串中的字符以它为中心(原创 2017-07-17 21:43:15 · 283 阅读 · 0 评论 -
SPOJ687 Repeats (后缀数组+lcp)
求循环节个数最大的子串的循环节个数。很绕吧。。基本和poj3693相同,此题要简单些。因为我先看了hzw的poj3693的题解。。所以我也写的是反过来做一遍求l。先入为主了呢。。网上还有很多人写的其实不需要反过来做一遍去求l,大家可以去借鉴下。。我觉得时间上差不多。。所以就懒得改了呢。。(思路有问题还是参考3693吧。。)#include #include #define N 50010原创 2017-07-18 18:48:11 · 389 阅读 · 0 评论 -
bzoj4199[luoguP2178]品酒大会[noi2015] (后缀数组+并查集)
bzoj上居然没题面。。可怕。洛谷上都有。首先,r相似其实就是lcp为r。那么就有个显然的做法。每次枚举lcp,按h分组,一组内有cnt个,则答案就是在cnt个数中选两个,C(cnt 2)。符号不会打,意思到了就好。。然后最大值。。想想怎么维护就好了。直接看代码吧。然后就可以拿到50分。而正解是这样的:r相似是不是至少有r+1相似个?那么r+1相似有多少个是不是跟r相似没啥关系??所以我们原创 2017-07-18 22:59:15 · 448 阅读 · 0 评论 -
bailian4122:切割回文(区间dp)
dp[i]表示把前i个都变成回文串最少需要切割的次数。每次枚举在j后面切一刀,暴力判断(j+1,i)是否是回文,如果是,那就是要切割dp[j]+1次。取最小即可。原创 2017-08-07 16:25:39 · 577 阅读 · 0 评论 -
bzoj4829 [TJOI2017]dna(后缀数组)
luogu3763有题面可以去看的说。。大牛分站开o2优化了(没错我就是这样才过的。)后缀数组处理一下lcp,然后枚举三次就好了。bzoj上我的总是T。嗯,一定是姿势不对。。不过我看神犇们都是用SAM写的,贼快。我也要去学习一下。。#include #include #define N 200005char s[N];int tst,n,len1,len2,m,st[N][19],lo原创 2017-07-23 13:20:00 · 592 阅读 · 0 评论 -
poj3461 Oulipo(KMP)
求单词W在文本T中的出现次数。KMP裸题。#include #include #define N 1000005#define M 10005;char s[N],t[N];int n,m,fail[N];inline void getfail(){ int k=0;fail[1]=0; for(int i=2;i<=m;++i){ while(k&&t[k+1]!=t[i原创 2017-07-23 14:54:33 · 365 阅读 · 0 评论 -
poj3080 Blue Jeans(后缀数组+二分答案)
和poj3450一模一样。。双倍经验,嗯,很好。#include #include #define N 10000int mm,m,n,ansl=0,a[N],id[N],tst;int rank[N<<1],rank1[N],tmp[N],count[N],sa[N],h[N];inline int min(int x,int y){return x<y?x:y;}inline原创 2017-07-19 15:59:53 · 360 阅读 · 0 评论 -
poj3693(后缀数组+lcp+rmq)
求循环节个数最大的子串。先穷举长度L,然后求长度为L 的子串最多能连续出现几次。首先连续出现1 次是肯定可以的,所以这里只考虑至少2 次的情况。假设在原字符串中连续出现2 次,记这个子字符串为S,那么S 肯定包括了字符r[0], r[L], r[L*2],r[L*3], ……中的某相邻的两个。所以只须看字符r[L*i]和r[L*(i+1)]往前和往后各能匹配到多远,记这个总长度为K,那原创 2017-07-18 18:56:12 · 726 阅读 · 0 评论 -
poj3294 Life Forms(后缀数组+二分答案)
求在≥k个串中出现过的最长子串.还是先都连起来,用特殊字符隔开,然后二分答案,按h分组,在一组内统计出现过的子串,满足条件就更新,注意可能有多个子串满足条件,按照顺序存下来就好了。大坑点见注释。(有人就拿char过了,很神。)#include #include #define N 102000int s[N];bool blank=0,vis[110];int belong[N],n原创 2017-07-17 21:38:55 · 404 阅读 · 0 评论 -
poj1743 Musical Theme(后缀数组+二分答案)
都做个差值,就解决了转调问题,然后就是求最长不重叠重复子串。二分答案即可。判断不重叠:按h分组后,记录一组中的最小id--mn和最大id--mx,if(mx-mn>=x)即存在不重叠的。#include #include #define N 20005inline int min(int x,int y){return x<y?x:y;}inline int max(int x,i原创 2017-07-17 21:33:06 · 359 阅读 · 0 评论 -
poj3450 Corporate Identity(后缀数组+二分答案)
题意:求多个串的最长公共子串把所有串都接在一起。。用特殊字符隔开。然后和两个串的一样,二分答案,每次判断这个长度是否可行。(分组,一组中出现在所有串中即满足)我以前写的SA太弱了。。还TLE了。。改进了一下下。#include #include #define N 805000int mm,m,n,ansl=0,a[N],id[N];int rank[N<<1],rank1原创 2017-07-17 21:27:33 · 562 阅读 · 0 评论 -
poj2774 Long Long Message(后缀数组)
很简单的后缀数组,求两个串的最长公共子串。把这两个串,用特殊字符隔开连在一起,更新合法的最大公共前缀即可。原创 2017-07-17 15:15:08 · 337 阅读 · 0 评论 -
poj3415Common Substrings(后缀数组+单调栈)
题目大意:给两个字符串,求所有满足 长度大于等于k的公共子串 的对数。思路:基本的,计算A 的所有后缀和B 的所有后缀之间的最长公共前缀的长度,把最长公共前缀长度不小于k 的部分全部加起来。(显然会TLE到死),所以我们把这两个串连起来(中间用特殊字符隔开),根据h数组进行分组,保证一组内字符串之间lcp都是大于等于k的。接下来的工作便是快速的统计每组中后缀之间的最长公共前缀之和。扫描一遍原创 2017-07-17 14:36:08 · 381 阅读 · 0 评论 -
bzoj1009 [HNOI2008]GT考试(KMP+DP+矩阵倍增)
f[i][j]表示前i位准考证号,匹配到了不吉利串第j位。我们考虑如何将f[i][j]转移到f[i+1][j].首先用kmp处理出fail数组,假设现在在做前i位匹配到了第j位,那么对于i+1位可能出现的每个字符我们都从j开始匹配,看能转移到哪里去。就是这样: f[0][0]=1; for(int i=0;i<=n;i++){ for(int j=0;j<m;j++){ for(i原创 2017-07-23 21:58:51 · 407 阅读 · 0 评论 -
bzoj3670 [noi2014] 动物园(kmp改编)
解释写代码里了。。noi出这样的题可是很神奇哟。(像我这样的蒟蒻可能场上也不一定能写出来吧。。)#include #include #define ll long long#define N 1000010#define mod 1000000007int tst,fail[N],cnt[N],m;char s[N];inline void getfail(){ //c原创 2017-07-23 22:57:08 · 331 阅读 · 0 评论 -
hdu4763 Theme Section(kmp)
题目大意:求最长的子串E,它既是串s的前缀又是后缀,还在串s的中间出现过(不能重叠)。直接从fai[len]开始枚举,在中间进行匹配,成功即可输出。#include #include #define N 1000010int tst,fail[N],m;char s[N];inline void getfail(){ int k=0;fail[1]=0; for(int i=原创 2017-07-23 23:34:46 · 326 阅读 · 0 评论 -
poj2752 Seek the Name, Seek the Fame(kmp)
从len开始,每一个fail[len]都可以。。不过要倒着输出。。原创 2017-07-28 22:26:42 · 265 阅读 · 0 评论 -
poj2406 Power Strings(kmp求循环节)
题目大意:求串s的最小循环节。用kmp处理出fail数组,len%(len-fail[len])如果为0,那么存在循环节,长度为len-fail[len],画一下图就可以自己证明啦#include #include #define N 1000010int fail[N],m;char s[N];inline void getfail(){ int k=0;fail[1]=0;原创 2017-07-24 14:02:49 · 482 阅读 · 0 评论 -
hdu4300 Clairewd’s message(KMP)
这题描述简直惊人。其实就是说先给你一个密码表。然后给你一个不一定完整的串。原串满足前一半是密码,后一半是明码。要求你最小的补全这个串。首先我们要明确:设给的串长度为len,则1...(len+1)/2的字母一定是密码。我们可以把这一部分作为模式串,去匹配后面的串。(当然因为我们假定后面的串都是明码,所以我们要把后面的串翻译成密码来匹配)。我们假设最后一位匹配到了模式串的第k位。则说明1..len-原创 2017-07-24 15:13:09 · 711 阅读 · 0 评论 -
bzoj1355: [Baltic2009]Radio Transmission(kmp求循环节)
画画图发现,就是m-fail[m]。。。#include #include #define N 1000010int fail[N],m;char s[N]; inline void getfail(){ int k=0;fail[1]=0; for(int i=2;i<=m;++i){ while(k&&s[k+1]!=s[i]) k=fail[k]; if(s[k+1原创 2017-07-24 16:37:15 · 373 阅读 · 0 评论 -
bzoj4698 [Sdoi2008] Sandy的卡片(后缀数组+二分答案)
差分,就像poj1743那样,多个串的最长公共子串,就像poj3450那样。然后就过了。据说kmp也可以写过这道题。。。各位可以试试。#include #include #define N 1100000int n=0,m=4000,tot,belong[N],s[N],ans=0;int sa[N],rank[N<<1],rank1[N],tmp[N],count[N],h[N];原创 2017-07-24 17:44:12 · 368 阅读 · 0 评论 -
CF471D MUH and Cube Walls(差分+KMP)
先差分,然后kmp匹配。注意m==1的情况。#include #include #define N 200010int s[N],t[N],n,m,fail[N],ans=0;inline int read(){ int x=0,f=1;char ch=getchar(); while(ch'9') {if(ch=='-')f=-1;ch=getchar();} whil原创 2017-07-24 18:11:23 · 442 阅读 · 0 评论 -
CF494B Obsessive String(KMP+DP)
这道题的题目真是太难读了。。。推了半天样例。其实就是让你求合法的集合数目。合法的集合定义为:1、集合中的所有串都是s的子串,且互不重叠 2、集合中的所有串都含有子串t。设串s长度为n,串t长度为m,我们首先用kmp在s中匹配t,匹配成功的位置我们打下标记flag[i]=1(s[i-m+1...i]=t[1..m]).以下角标均针对串s:设dp[i]表示合法且集合中最后一个子串为s[j.原创 2017-07-24 22:23:00 · 710 阅读 · 0 评论 -
hdu4333 Revolving Digits(kmp+exkmp)
首先注意到如果数字是有循环节的,那么每次挪位会有重复的。所以我们先用kmp处理循环节,一共会有循环节长度个不同的合法串。我们把原串接在自己后面。那么每一次我们取的s[i..i+m-1]即为一个合法串(i=1...n)。用exkmp处理出会用到的n个串与原串的lcp,如果lcp>=m,则相等,否则比较第一个不同的位,即s[i+lcp]与s[lcp+1]。(我的exkmp写得实在是丑。。。凑合看吧。。原创 2017-07-25 20:41:46 · 312 阅读 · 0 评论 -
hdu3613 Best Reward(KMP)
本题难度在于判断回文前缀和回文后缀。我们设原串为s1,把原串翻转后得到的串记为s2.以s1为模式串去匹配s2,最后匹配到的位置我们记为k,k就是最长回文前缀长度。根据fail的性质,每一次fail[k]到的位置都满足前缀回文。那么我们就把这些回文前缀都标记了。回文后缀同理,我们以s2为模式串去匹配s1,那么k就是s2的最长回文前缀长度,即s1的最长回文后缀长度。同样处理,把这些回文后缀标记。然后我原创 2017-07-25 21:25:23 · 327 阅读 · 0 评论 -
hdu2594(KMP水题)
把俩串联在一起,用‘#’隔开,答案就是fail[n]#include #include #define N 50010char s[N<<1],s2[N];int n,fail[N<<1];inline void getfail(){ int k=0;fail[1]=0; for(int i=2;i<=n;++i){ while(k&&s[k+1]!=s[i]) k=fail原创 2017-07-25 21:47:23 · 345 阅读 · 0 评论 -
hdu4843 [noi2000] 古城之谜 (Trie+dp)
做出这道题关键在于理解语法。其中名词短语和动词短语给出的都是递归定义,可以转化为更直观的, <名词短语> ::= {<辅词>} <名词>, <动词短语> ::= {<辅词>} <动词>, 也就是以一个名词或动词结尾,前面可以加上任意多个辅词。而句子就是要以名词短语开头,后面的名词短语和动词短语交替出现。分析出语法结构,就可以进行动态规划。定义词性 j={0,1,2,3}。 f[i][0][原创 2017-08-17 13:48:32 · 863 阅读 · 0 评论 -
bzoj2251 [2010Beijing WC]外星联络(后缀数组+暴力)
求所有出现次数大于1的字串。。用后缀数组处理出h数组,每个子串第一次出现时,往后扫,看重复了几次。n=3000,暴力即可。原创 2017-08-03 12:58:59 · 453 阅读 · 0 评论 -
hdu1841(KMP)
就是求包含两个给定串的最短串。那长度最长是len1+len2,如果有重叠的就减掉就最短了。拿s2匹配一次s1,再拿s1匹配一次s2,记录最大重叠。#include #include #define N 1000010int tst,fail[N];char s1[N],s2[N];inline int max(int x,int y){return x>y?x:y;}inline原创 2017-07-25 22:18:11 · 379 阅读 · 0 评论 -
poj2185 Milking Grid(二维KMP+最小覆盖矩阵)
题意:在字符矩阵中找出一个最小子矩阵,使其多次复制所得的矩阵包含原矩阵。首先我们计算答案矩阵的列数,叫做宽。对每行都计算出所有的重复子串可能的长度,如:AAAABAAA,可能的重复子串长度为:5,6,7,8.如何计算呢?k从m开始,每次k-fail[k]即为重复子串长度,k=fail[k],直到k=0.每行中都出现过的最小长度即为答案矩阵的宽。(遇到一个可能长度就计数器+1,最后从小到大扫一遍,次原创 2017-07-26 11:38:06 · 429 阅读 · 0 评论 -
bzoj3230 相似子串(SA+lcp+二分)
首先用后缀数组处理出h数组。因为要问子串的排名,所以我们再记一个数组num[i],表示前i个后缀有几个本质不同的子串。然后我们用二分查找就可以找到排序后的第i个子串是谁了。然后就是求一下lcp了。。还有反过来的lcp。。算清角标就好了。。还有很坑的一点:可能有超过int范围个实质不同的字串=,=.#include <cstdio>#include <cstring>#include <algor原创 2017-08-03 16:20:00 · 458 阅读 · 0 评论 -
hdu3068 最长回文(manacher)
求最长回文子串,manacher模板题。就是充分利用已知信息,尽量减少冗余操作。因为mx是始终右移的,所以是O(n)的。#include #include #define N 110010char s[N<<1],str[N];int n,p[N<<1];//p[i]表示以s[i]为中心向一边延伸的最长长度(含i)//即s[i-p[i]+1]...s[i]=s[i]..s[i+p[i原创 2017-07-26 17:14:17 · 310 阅读 · 0 评论 -
hdu3294 Girls' research(manacher)
manacher模板吧。。就多了个翻译一下输出串。#include #include #define N 200010char op[1],str[N],s[N<<1];int p[N<<1],n;inline int min(int x,int y){return x<y?x:y;}int main(){// freopen("a.in","r",stdin); wh原创 2017-07-26 18:00:06 · 311 阅读 · 0 评论 -
hdu4513 (manacher)
题意:求最长回文子串,且从最左到mid是单调不降的。基本同manacher板子,就加了一个条件:s[i+p[i]]#include #include #define N 100010inline int read(){ int x=0,f=1;char ch=getchar(); while(ch'9'){if(ch=='-') f=-1;ch=getchar();} wh原创 2017-07-26 21:14:47 · 460 阅读 · 0 评论 -
poj3974 Palindrome(manacher)
一把好水???原创 2017-07-28 22:30:07 · 348 阅读 · 0 评论 -
bzoj2342 [Shoi2011]双倍回文(manacher+暴力/set)
题意:求一个最长的回文串,满足它的后半段也是个偶数回文串。 首先用manacher处理出f数组,表示以i,i+1为对称轴的最长偶数回文的长度的一半(根据题目不难发现只有偶数回文才有用)(造样例推一推和p数组的关系)。然后枚举以x,x+1为对称轴的双倍回文,检验是否存在(枚举y,看以y,y+1为对称轴且过x+1点的回文是否存在 ,显然y最大到x+f[x]/2,最小到x+1)原创 2017-07-28 21:21:35 · 379 阅读 · 0 评论