程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> HDU 1686 Oulipo

HDU 1686 Oulipo

編輯:關於C語言

題意:求模式串在主串中出現的次數【可重疊】

Sample Input
3
BAPC
BAPC
AZA
AZAZAZA
VERDI
AVERDXIVYERDIAN

Sample Output
1
3
0

 

對代碼中神奇的地方進行解釋:

 

那麼3的意義可以表示為 
 
可見next[len2]的意義:前綴和後綴的最長匹配長度

現在就以這個為模式串模擬一下:
主串:    A B A B A B C A B A B A A B 
 
模式串:A B A B C A B A

匹配成功後下一步的情況應為:
主串:    A B A B A B C A B A B A A B 
 
模式串:                                A B A B C A B A
指針直接移動到紅色部分進行匹配

如何理解呢?
我們先不看最後那2個字符A和B,就可以發現最大前綴【指前綴和後綴的最長匹配長度】直接挪動到最大後綴那裡了,為什麼可以這樣呢?因為前面都是顯然不能夠匹配成功的
可以向前移動一位試試看:
主串:    A B A B A B C A B A B A A B 
 
模式串:                            A B A B C A B A
我們先不看最後那2個字符A和B,可以看到現在是4長度的前綴與4長度的後綴比較,顯然不
可匹配,因為最大匹配長度是3【指前綴和後綴的最長匹配長度】,顯然再向前移也不行的


第一次長篇大論,若有錯誤或不明白之處,請指出
C++代碼 
#include <iostream>  
#include <fstream>  
#include <algorithm>  
#include <string>  
#include <set>  
//#include <map>  
#include <queue>  
#include <utility>  
#include <stack>  
#include <list>  
#include <vector>  
#include <cstdio>  
#include <cstdlib>  
#include <cstring>  
#include <cmath>  
#include <ctime>  
#include <ctype.h>  
using namespace std;  
#define L1 1000005  
#define L2 10005  
 
int len1, len2, next[L2], res;  
char s[L1], p[L2];  
 
void get_next ()  
{  
    int k = -1, j = 0;  
    next[0] = -1;  
    while (j < len2)    //這裡必須要推導出next[len2]  
    {  
        if (k == -1 || p[k] == p[j])  
        {  
            j++, k++;  
            if (p[k] != p[j])  
                next[j] = k;  
            else next[j] = next[k];  
        }  
        else k = next[k];  
    }  
    /*for (j = 0; j <= len2; j++) 
        cout << next[j] << ; 
    cout << endl;*/ 
}  
void kmp ()  
{  
    int i = 0, j = 0;  
    while (i < len1 && j < len2)  
    {  
        if (j == -1 || s[i] == p[j])  
            i++, j++;  
        else j = next[j];  
        if (j >= len2)      
            res++, j = next[j];    //灰常神奇的地方,用到next[len2],效率大大提高  
    }  
}  
int main()  
{  
    int t;  
    scanf ("%d", &t);  
    while (t--)  
    {  
        scanf ("%s%s", p, s);  
        len1 = strlen(s);  
        len2 = strlen(p);  
        res = 0;  
        get_next();  
        kmp ();  
        printf ("%d ", res);  
    }  
    return 0;  
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved