[模板] [KMP] 字符串匹配

拓展kmp


int Next[MAXN], extand[MAXN];

char s[MAXN];

void getNext(char *T)
{// Next[i]: 以第i位置开始的子串 与 T的公共前缀 
	int i, length = strlen(T);
	Next[0] = length;
	for(i = 0; i < length - 1 && T[i] == T[i+1]; i++);
	Next[1] = i;
	int a = 1;
	for(int k = 2; k < length; k++)
	{
		int p = a+Next[a]-1, L = Next[k-a];
		if((k - 1) + L >= p )
		{
			int j = (p - k + 1) > 0 ? (p - k + 1) : 0; 
			while(k + j < length && T[k + j] == T[j]) 
				j++;// 枚举(p+1,length) 与(p-k+1,length) 区间比较 
			Next[k] = j, a = k;
		} 
		else 
			Next[k] = L;
	} 
}

void getextand(char *S,char *T)
{
	memset(Next,0,sizeof(Next));
	getNext(T);
	int Slen = strlen(S), Tlen = strlen(T), a = 0;
	int MinLen = Slen > Tlen ? Tlen : Slen;
	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 = Next[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;         
	}
}

KMP 

#include <iostream>
using namespace std;

typedef long long ll;

const int MAXN = 1e5 + 10;

string a, text;

ll pre[100010] = {-1};


void prefix_table(string mode)
{
    for(int i = 1, j = 0; i < mode.length(); i++)
    {
        if(mode[i] == mode[j])
        {
            pre[i + 1] = pre[i] + 1;

            j++;
        }
        else    //若匹配不上再次匹配时从零开始
        {
            j = 0;

            if(mode[i] == mode[j])    //从零的第一个单独判断一
            {    
                pre[i + 1] = 1;
                
                j++;
            }

        }
    }
}

int judge(int beg, int end,int lenm) //向后跳转匹配
{
    int i = beg - 1, j = 0, ans = 0;
    
    while(i < end)
    {
        if(j == lenm - 1 && text[i] == a[j])
        {
            ans++;
        }
        if(text[i] == a[j])
        {
            i++;
            j++;
        }
        else
        {
            j = pre[j];
            if(j==-1)
            {
                i++;
                j++;
            }
        }
    }
    return ans;
}


int main()
{
    int lent, lenm, t;

    cin>>lent>>lenm>>t;

    cin>>text>>a;

    prefix_table(a);
    
    while(t--)
    {
        int beg, end;

        cin>>beg>>end;
        
        cout<<judge(beg, end, lenm)<<endl;
    }
    return 0;
}

 

posted @ 2018-08-04 11:20  张浦  阅读(78)  评论(0编辑  收藏  举报