字符串(1)---KMP & 扩展KMP & Manacher

练习:点击打开链接

字符串也是ACM中的重头戏,基本内容有KMP ,扩展KMP, Manacher ,AC自动机,后缀数组,后缀自动机.按照专题来做共分三部分. LCS LIS LCIS不知道算不算....点击打开链接

小技巧:匹配问题不区分大小写,则将其全部转为小写.

暴力匹配: 用strstr函数就能解决       I M N Z(枚举长度 三份)

一.KMP算法

解决单一模式串匹配问题.

利用失配后的nxt数组减少移位,达到O(n)级别.资料自行百度.

延展:

1.求最小循环节 点击打开链接   就是len-nxt[len]                D E(这个题目意思是i为止可以表示成循环的字符) F G

2.求各个循环节  P(先求出最小循环节,然后进入nxtval[i]再求最小循环节累加就是第二小依次循环)

3.字符串最大最小表示法 O(最大最小 循环长度就是最小循环节) P(都转为最小 map存放)

4.模式串成功匹配次数(可以有重叠) 匹配成功后j=nxt[j]     B

5.模式串成功匹配次数(不能有重叠) 匹配成功后j=0          C

6.既是前缀又是后缀    用nextval递归往后  H

7.一个串的最长前缀另一个串的最长后缀,连起来求nxt 完了判断最长的不要大于字符串长就行

8.各种前缀可匹配的次数 自左至右计算nxt[]的dp[] ,dp[i]=dp[nxt[i]]+1 ans+=dp[i]

9.

二.扩展KMP

求extand[] 表示以i起始的后缀串与模式串匹配的长度.nxt[] 表示以i起始模式串的后缀串与模式串匹配的长度  点击打开链接

1.利用nxt数组求最长后缀串匹配长度 裸EXKMP    L

三.最长回文

一个串中最长的连续回文.p[i] 以i为中点的最长回文数.点击打开链接

U V W X

其中V是吉哥系列2要求连续 规模10^5,有个要求是大于等于,所以加个限制条件就行 系列1使用的是LCS,不要求连续规模10^2

不要求连续的回文使用转置再求LCS (HDU1513 点击打开链接)

///核心思想是利用之前已经"匹配"信息减少j移动
///EXKMP方法是记录一个最远匹配位置
///KMP
void getnxt(){
	int j = -1;
	nxt[0] = -1;
	for(int i = 0;i < M;){
		if(j == -1 || s2[i] == s2[j]){
			i++,j++;
			if(s2[i] == s2[j]) nxt[i] = nxt[j];
			else nxt[i] = j;
		}
		else j = nxt[j];
	}
}
int KMP(){
	getnxt();
	int i = 0,j = 0;
	while(i < N){   ///这个写错了,不是字符串\0的意思
		if(j == -1 || s1[i] == s2[j])
			i++,j++;
		else j = nxt[j];
		if(j==M) return i-M+1;
	}
	return -1;
}
///EXKMP
void Getnxt(const char *T){
     int len=strlen(T),a=0;
     nxt[0]=len;
     while(a<len-1 && T[a]==T[a+1]) a++;
     nxt[1]=a;
     a=1;
     for(int k=2;k<len;k++){
         int p=a+nxt[a]-1,L=nxt[k-a];
         if( (k-1)+L >= p){
             int j = (p-k+1)>0 ? (p-k+1) : 0;
             while(k+j<len && T[k+j]==T[j]) j++;
             nxt[k]=j;
             a=k;
         }
         else
             nxt[k]=L;
     }
}
void GetExtand(const char *S,const char *T){
     Getnxt(T);
     int slen=strlen(S),tlen=strlen(T),a=0;
     int MinLen = slen < tlen ? slen : tlen;
     while(a<MinLen && S[a]==T[a]) a++;
     extand[0]=a;
     a=0;
     for(int k=1;k<slen;k++){
         int p=a+extand[a]-1, L=nxt[k-a];
         if( (k-1)+L >= p){
             int j= (p-k+1) > 0 ? (p-k+1) : 0;
             while(k+j<slen && j<tlen && S[k+j]==T[j]) j++;
             extand[k]=j;
             a=k;
         }
         else
             extand[k]=L;
     }
}
/**
最长回文子串,求的是连续.如果可以不连续则reserve再LCS
http://blog.csdn.net/xingyeyongheng/article/details/9310555
**/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 150000
char fst[maxn];
char sed[2*maxn+2];
int  p[2*maxn+2];
int Manacher(){
    int len = strlen(fst);
    int maxlen =0,id=0;
    for(int i = 0;i < len;i++){
        sed[i*2+1] = '#';
        sed[i*2+2] = fst[i];
    }
    sed[2*len+1] = '#';
    sed[2*len+2] = 0;
    sed[0] = '@';
    len = 2*len+1;
    for(int i = 2;i < len;i++){
        if(p[id] + id > i) p[i] = min(p[2*id-i],p[id]+id-i);
        else p[i] = 1;///公式化简一下 k=i-id  i-k=2id-i
        while(sed[i-p[i]] == sed[i+p[i]]) ++p[i];///害怕这里越界
        if(id+p[id]<i+p[i]) id=i;///i+p[id] 这个写错了....我擦
        maxlen = max(maxlen,p[i]);
    }
    return maxlen-1;
}

int main(){
    while(~scanf("%s",fst))
        printf("%d\n",Manacher());
    return 0;
}

时间: 2024-10-08 11:32:08

字符串(1)---KMP & 扩展KMP & Manacher的相关文章

[kuangbin带你飞]专题十六 KMP &amp; 扩展KMP &amp; Manacher :G - Power Strings POJ - 2406(kmp简单循环节)

[kuangbin带你飞]专题十六 KMP & 扩展KMP & Manacher G - Power Strings POJ - 2406 题目: Given two strings a and b we define a*b to be their concatenation. For example, if a = "abc" and b = "def" then a*b = "abcdef". If we think of

KMP &amp; 扩展KMP &amp; Manacher 专题

KMP & 扩展KMP & Manacher  专题 先来模版: void getNext(int *b,int m) { Next[0]=-1; int i=0,j=-1; while(i<m&&j<m){ if(j==-1||b[i]==b[j]) Next[++i]=++j; else j=Next[j]; } } int kmp(int *a,int *b,int n,int m) { getNext(b,m); int i=0,j=0; while(i

KMP&amp;扩展KMP

声明 本文将不断加入例题,稍安勿躁,今天的总结争取9:30写完. KMP KMP,中文名字叫字符串匹配,用于解决一类字符串匹配问题. 先下一些定义: \(s\)表示匹配串,\(t\)表示文本串,字符串匹配用于求\(s\)在\(t\)中的出现情况. \(n\)和\(m\)分别为\(s\)和\(t\)的字符串串长. \(nxt_i\)表示对于\(s\)的前缀\(s_{1...i}\)的最长公共前后缀. 首先我们先想一想\(nxt_i\)对于求解问题有怎样的帮助. 暴力匹配 我们对于每一个\(t_i=

hdu 4300 Clairewd’s message(kmp/扩展kmp)

题意:真难懂.. 给出26个英文字母的加密表,明文中的'a'会转为加密表中的第一个字母,'b'转为第二个,...依次类推. 然后第二行是一个字符串(str1),形式是密文+明文,其中密文一定完整,而明文可能不完整(也可能没有). 求出最短的完整的字符串(密文+明文). 思路: 1.用kmp来做: 首先肯定的是,给定的串中明文长度一定小于等于密文.也就是说明文长度小于等于总长的一半. 于是,取总长的后一半作为主串,然后把串反翻译一遍得到str2,然后用str2与str1的后一半进行匹配.首次把st

8.2 kmp 扩展kmp

假设一母串S,子串P KMP:用于求解子串P在母串S中第一次出现的位置,或是在母串S中出现的次数.(最长公共前缀后缀) next数组的含义:next[i]表示前面长度为i的子串中,前缀和后缀相等的最大长度. 拓展kmp是对KMP算法的扩展,它解决如下问题:(最长公共前缀) 定义母串S,和子串T,设S的长度为n,T的长度为m,求T与S的每一个后缀的最长公共前缀,也就是说,设extend数组,extend[i]表示T与S[i,n-1]的最长公共前缀,要求出所有extend[i](0<=i<n).

[kuangbin带你飞]专题十六 KMP &amp; 扩展KMP &amp; Manacher B - Oulipo HDU - 1686(kmp)

B - Oulipo HDU - 1686 题目链接:https://vjudge.net/contest/70325#problem/B 题目: The French author Georges Perec (1936–1982) once wrote a book, La disparition, without the letter 'e'. He was a member of the Oulipo group. A quote from the book: Tout avait Pa

kuangbin专题十六 KMP&amp;&amp;扩展KMP HDU3613 Best Reward(前缀和+manacher or ekmp)

After an uphill battle, General Li won a great victory. Now the head of state decide to reward him with honor and treasures for his great exploit. One of these treasures is a necklace made up of 26 different kinds of gemstones, and the length of the

[kuangbin带你飞]专题十六 KMP &amp; 扩展KMP &amp; Manacher H - Seek the Name, Seek the Fame POJ - 2752(kmp的next数组应用)

H - Seek the Name, Seek the Fame POJ - 2752 题目链接:https://vjudge.net/contest/70325#problem/H 题目: The little cat is so famous, that many couples tramp over hill and dale to Byteland, and asked the little cat to give names to their newly-born babies. Th

kuangbin专题十六 KMP&amp;&amp;扩展KMP POJ3080 Blue Jeans

The Genographic Project is a research partnership between IBM and The National Geographic Society that is analyzing DNA from hundreds of thousands of contributors to map how the Earth was populated. As an IBM researcher, you have been tasked with wri