字符串算法總結(模板)

目錄

KMP模式匹配算法

Manacher最長迴文子串算法


KMP模式匹配算法

給出長度n的主串和長度m的模式串進行模式匹配,複雜度O(n+m)

預處理出失敗指針(最長公共前後綴),進行平攤爲O(1)的轉移

int nxt[maxn];
void build_next(char *s){
	int len = strlen(s+1);
	for(int i=2,j=0;i<=len;i++){ // j爲之前已匹配成功的長度 
		while(j && s[i]!=s[j+1]){
			j = nxt[j];
		}
		if(s[j+1]==s[i]){
			j++;
		}
		nxt[i] = j;
	}
}

void Kmp(char *T,char *P){
	build_next(P);
	int la = strlen(T+1);
	int lb = strlen(P+1);
	for(int i=1,j=0;i<=la;i++){ // j爲之前已匹配成功的長度
		while(j&&T[i]!=P[j+1]){ // 通過失敗指針找到可以成功的位置或找不到 
			j = nxt[j];
		}
		if(T[i]==P[j+1]){ // 匹配成功  匹配成功長度+1 
			j ++;
		}
		if(j==lb){
			printf("%d\n",i-lb+1);
			j = nxt[j];
		}
	}
}

Manacher最長迴文子串算法

給定長度爲n的字符串,O(n)的複雜度找到其最長迴文子串的長度

利用之前已找出的迴文串的長度,先確定一部分的迴文串長度,然後在這個基礎上延伸

char s[maxn],str[maxn];
int n,len[maxn]; // 以i爲中心的最長迴文串的半徑 

void init(){
	str[0] = str[1] = '#'; // 將字符串預處理出來 
	for(int i=0;i<n;i++){
		str[2*i+2] = s[i];
		str[2*i+3] = '#';
	}
	n = n*2 + 2;
	str[n] = 0;
}

int Manacher(){
	init();
	int mx=0,id=0,ans=0;
	for(int i=1;i<n;i++){
		if(i<mx){
			len[i] = min(len[2*id-i],mx-i); //該點的半徑在對稱點的基礎上延伸 
		}else{
			len[i] = 1;
		}
		for(;str[i-len[i]] == str[i+len[i]];len[i]++);
		if(i+len[i] > mx){ // 記錄之前找到的最長迴文子串的延伸的最右邊和中心點 
			mx = i+len[i];
			id = i;
		}
		ans = max(ans,len[i]);
	}
	return ans - 1;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章