字串匹配。給你兩個字串,尋找其中乙個字串是否包含另乙個字串。
如果包含,返回包含的起始位置。如下面兩個字串:
char *str = "bacbababadababacambabacaddababacasdsd";
char *ptr = "ababaca";
str有兩處包含ptr。分別在str的下標10,26處。
我們從原始字串str(假設長度為n)的第乙個下標、
選取和ptr長度(長度為m)一樣的子字串進行比較。
如果一樣,就返回開始處的下標值,不一樣,選取str下乙個下標。
繼續選取長度為m的字串比較,直到str的末尾(即下標移動到n-m)。
這樣的時間複雜度是o(n*m)。
kmp演算法:可以實現複雜度為o(m+n)。
充分利用了目標字串ptr的性質(比如裡面部分字串的重複性,
即使不存在重複字段,在比較時,實現最大的移動量)。
考察目標字串ptr:ababaca
這裡我們要計算乙個長度為m的轉移函式next。
next陣列的含義就是乙個固定字串的 最長字首 和 最長字尾 相同的長度。
比如:abcjkdabc,那麼這個陣列的最長字首和最長字尾相同必然是abc。
cbcbc,最長字首和最長字尾相同是cbc。
abcbc,最長字首和最長字尾相同是不存在的。
預處理的陣列next:next [ i ]表示「str中以i結尾的非字首字串(上文說的字尾)」
與「str的字首」能夠匹配到的最長長度。
// a="ababacb"; 長度為m
// b="abababaababacb"; 長度為n
(注意:以下**的字串輸入都從1開始)
//next[i]
next[1]=0; j=0;
for(int i=1;i0&&a[i+1]!=a[j+1]) j=next[j];
//↑自身無法繼續匹配且j還沒減到0,考慮返回匹配的剩餘狀態
if(a[i+1]==a[j+1]) j++; //這一位匹配成功
next[i+1]=j; //記錄這一位向前的最長匹配
}
陣列f:f [ i ] 表示「 ptr中以 i 結尾的子串 」與「 str的字首 」的最長匹配長度。
在b串中尋找a串出現的位置:
j=0;
for(int i=0;i0) j=next[j];
//↑不能繼續匹配且j還沒減到0(之前的匹配有剩餘狀態)
if(b[i+1]==a[j+1]) j++; //匹配加長,j++
if(j==m) //【↑↑巧妙↑↑這裡不用返回0,只用返回上一匹配值】
}
求f陣列(a與b最大的匹配長度):
//f[i]
j=0;
for(int i=0;i0) j=next[j];
//↑不能繼續匹配且j還沒減到0(之前的匹配有剩餘狀態)
//↑↑↑或a在b中找到完全匹配
if(b[i+1]==a[j+1]) j++; //匹配加長,j++
f[i+1]=j; //此位置和先前組成的最長匹配
// (if(f[i+1]==m),此時a在b中找到完全匹配)
}
(1)剪花布條(hdu2087)
#include #include #include #include #include #include #include #include #include using namespace std;
typedef long long ll;
typedef unsigned long long ull;
//【剪花布條】能從花布條中剪出多少小花條? [注意:不能重疊!]
char a[1009],b[1009];
int nextt[1009],n,m;
void pre()
}int kmps() //j=0,保證不重疊
if(b[j+1]==a[i+1]) j++; //匹配加長,j++
}return ans;
}int main()
return 0;
}
(2)字串週期(poj 2406)
#include #include #include #include #include #include #include #include #include using namespace std;
typedef long long ll;
typedef unsigned long long ull;
/*【power strings】poj2406
給出乙個不超過1e6的字串,求這個字串最多有多少個週期。 */
char a[1000005];
int nextt[1000005],n;
void pre()
}int main()
return 0;
}
(3)最小迴圈元長度和最大迴圈次數(poj1961)
#include #include #include #include #include #include #include #include #include using namespace std;
typedef long long ll;
typedef unsigned long long ull;
/*【period】poj 1961
給你乙個字串,求這個字串到第i個字元為止的最小迴圈元長度和最大迴圈次數。 */
char a[1000005];
int nextt[1000005],n,t;
void pre()
}int main()
printf("\n");
}return 0;
}
(4)bzoj 1355/1511/3620/3942
【等待填坑中σ( ° △ °|||)︴】
暖 墟 AC自動機 多模式串的匹配運用
1.將所有模式串構建成 trie 樹 2.對 trie 上所有節點構建字首指標 類似kmp中的next陣列 3.利用字首指針對主串進行匹配 字典樹的構建過程是這樣的,當要插入許多單詞的時候,我們要從前往後遍歷整個字串,當我們發現當前要插入的字元其節點再先前已經建成,我們直接去考慮下乙個字元即可,當我...
模式匹配 KMP演算法
字串匹配演算法 include includeusing namespace std define ok 1 define error 0 define overflow 2 typedef int status define maxstrlen 255 使用者可在255以內定義最長串長 typed...
模式匹配KMP演算法
前些日子在為目前該學習什麼而苦惱,就問了一下已經從事多年軟體開發的表哥,他說乙個程式設計師要走的遠,就要學好資料結構和演算法,於是我就重新開始學習資料結構和演算法了 拿起以前上過的資料結構看,看到第四章串的模式匹配時,頗感興趣,就寫了一下程式,實踐了一下。感覺還蠻爽,於是就把以下幾個重要的函式放在此...