1. 程式人生 > 遊戲攻略 >《雲頂之弈》11.16版本惡魔炮手詳細解讀

《雲頂之弈》11.16版本惡魔炮手詳細解讀

oi-wiki

應用:在字串中查詢子串,求迴圈節長度等。

字串匹配:

暴力思想,列舉每一個每一個文字串元素,然後從這一位開始不斷向後比較,每次比較失敗之後都要從頭開始重新比對,複雜度易被卡成 \(O(nm)\)

而對於 KMP 演算法,在每次失配之後,不會從頭重新開始列舉,而是根據已得知的資料,從失配後的特定位置開始匹配,使複雜度優化至 \(O(n+m)\).

適配後的特定位置:失配陣列(見這裡

lg模板

code:

#include<bits/stdc++.h>
using namespace std;

const int N=1e6+10;
char a[N],b[N];int k[N],la,lb;//k陣列即為失配陣列

int main()
{
	scanf("%s%s",a+1,b+1);
	la=strlen(a+1),lb=strlen(b+1);
	int j=0;
	for(int i=2;i<=lb;i++)
	{
		while(j/*如果回跳到第一個字元就不用再回跳了*/&&b[j+1]!=b[i]) j=k[j];
		if(b[j+1]==b[i]) j++;//通過自己匹配自己來得出每一個點的kmp值 
		k[i]=j;//i+1失配後跳的地方
	}j=0;
	for(int i=1;i<=la;i++)
	{
		while(j&&b[j+1]!=a[i]) j=k[j];//如果失配 ,那麼就不斷向回跳,直到可以繼續匹配 
		if(b[j+1]==a[i]) j++;//如果匹配成功,那麼對應的模式串位置加1
		if(j==lb) printf("%d\n",i-lb+1),j=k[j];
	}
	for(int i=1;i<=lb;i++) printf("%d ",k[i]);
	return 0;
}

迴圈節長度: len-kmp[len]

code:

void KMP()
{
    for(int i=1;i<len;i++)
    {
        while(j>0&&a[j+1]!=a[i+1]) j=kmp[j];
        j=a[j+1]==a[i+1]?j+1:j;
        kmp[i+1]=j;
    }
    cout<<len-kmp[len];
}

\(\texttt{End.}\)