FJUT OJ 2584 QAQ的變強魔咒(KMP)
阿新 • • 發佈:2017-08-29
scan input 分割 pre next 小寫字母 先後 ace void
突然有一天默默無聞的QAQ變成了FJUTOJ的終極大BOSS,而使得QAQ變強的是QAQ掌握有一個由小寫字母組成魔咒。
作為QAQ小弟的V_Dragon偷偷的聽到了一部分連續魔咒,V_Dragon非常的激動,因為這一部分魔咒能使得菜雞V_Dragon
變強100倍。但V_Dragon的聽力不是很好,有一些聽不清,也有可能聽錯。但V_Dragon有個神奇的魔法,可以將他沒聽
清的部分變成QAQ魔咒中的任意部分(也可以為空),現在要聰明的ACMer你來判斷V_Dragon有沒有聽錯。
(題目沒看懂? 沒關系,看樣例!!)
Input輸入包含多組測試數據
輸入第一行表示QAQ掌握的魔咒,1<=s1<=100000,只包含小寫字母
輸入第二行表示V_Dragon偷聽到的魔咒,1<=s2<=100000,‘*‘表示V_Dragon沒聽清的部分。只包含小寫字母和‘*‘
Output判斷V_Dragon是否聽錯。沒聽錯輸出YES,聽錯輸出NO
SampleInputabcdef a*b*e abcdef a*c*f abcdef ac*f abc bcSampleOutput
YES YES NO YES
提示: 樣例1:第一個‘*‘表示一個空串,第二個‘*‘表示cd,變成abcde是魔咒的子串 樣例2:第一個‘*‘表示b,第二個‘*‘表示de,變成abcdef是魔咒的子串 樣例3:‘*‘不管代表什麽都可能是魔咒的子串,所以V_Dragon肯定聽錯了 樣例4:懶得解釋
分析:在字符串2中,我們可以看成它是由*分割的幾個字符串.如果要符合要求,那麽這幾個字符串就一定會按照順序在串1中出現,
所以我們把這幾個由*分割的字符串與串1進行KMP操作,找到它在串1中出現,並且滿足先後順序要求的第一個位置。
如果串2中所有的由*分割的字符串都能找到這樣的位置 就輸出 YES 否則輸出NO
要特別註意的是 由單個和多個*號組成的串2 都輸出YES
代碼如下:
#include <cstdio> #include <iostream> #include <cstring> using namespace std; const int N = 1000002; int Next[N]; char S[N], T[N]; char r[N]; int slen, tlen;//註意每次一定要計算長度 int rlen; int left1; int right1; void getNext() { int j, k; j = 0; k = -1; Next[0] = -1; while(j < tlen)if(k == -1 || T[j] == T[k]) Next[++j] = ++k; else k = Next[k]; } /* 返回模式串T在主串S中首次出現的位置 返回的位置是從0開始的。 */ int KMP_Index() { int i = 0, j = 0; getNext(); while(i < slen) { if(j == -1 || S[i] == T[j]) { i++; j++; } else j = Next[j]; if(j == tlen){ if(i-tlen>left1) return i - tlen; j=Next[tlen]; } } return -1; } int main() { int TT; int i, cc,cnt,flag; scanf("%d",&TT); while(scanf("%s",S)!=EOF) { flag=1; scanf("%s",r); slen = strlen(S); rlen=strlen(r); r[rlen]=‘*‘; rlen++; r[rlen]=0; cnt=0; left1=-1; for(int i=0;i<rlen;i++) { if(r[i]!=‘*‘) { T[cnt++]=r[i]; continue; } else { if(cnt==0)continue; T[cnt]=0; tlen=cnt; right1=KMP_Index(); if(right1<=left1) { flag=0; break; } else{ left1=right1; cnt=0; } } } flag==1?puts("YES"):puts("NO"); } return 0; }
FJUT OJ 2584 QAQ的變強魔咒(KMP)