http://acm.hdu.edu.cn/showproblem.php?pid=3901
多校2011 (7)
題意:給定一個text串,和一個帶*和?的模式串,看是否能匹配(題目說的匹配,但其實只是子串匹配就能過,標程是子串匹配的?,坑爹啊。。。只要是子串就可以了,開始以爲一定要全匹配。。。),長度100000
*可以代表0或多個字符
?一定代表1個字符
分析:
對子串匹配:
對?而言,保證只要是?的地方對任何字符都匹配。。所以只要改動next函數和匹配函數裏面,保證出線?都匹配即可。。。對*而言,相當於把原模式串分割成s1,s2,s3....對這些串依次去匹配,每次都返回了最靠前的匹配的位置,到最後如果不能匹配了說明無法匹配。。。
注意最後模式串可能剩一大堆***,判斷一下下。。。
對全匹配:
待定。。。
代碼:
子串匹配
#include<iostream>
using namespace std;
const int N=100010;
char t[N], s[N], tmp[N];
int next[N], tn, sn, flag;
void getnext(char *s)
{
int len=strlen(s);
int i=0, j=-1;
next[0] = -1;
while(i<len)
{
if(j==-1 || s[i]==s[j] || s[i]=='?' || s[j]=='?')
next[++i] = ++j;
else
j = next[j];
}
}
int getindex(int ti, char tmp[])
{
int len = strlen(tmp);
int j=0;
while(ti<tn && j<len)
{
if(j==-1 || t[ti]==tmp[j] || tmp[j]=='?')
{
ti++, j++;
}
else
j = next[j];
}
if(j==len)
return ti;
return -1;
}
int main()
{
int i, j, k, l;
while(scanf("%s %s", t, s)!=EOF)
{
tn = strlen(t);
sn = strlen(s);
for(i=0,j=0; i<tn && j<sn; )
{
for( ; j<sn&&s[j]=='*'; j++);
for(k=j; k<sn&&s[k]!='*'; k++);
for(l=j; l<k; l++)
tmp[l-j] = s[l];
tmp[l-j] = '\0';
getnext(tmp);
flag = getindex(i, tmp);
if(flag==-1)
break;
i = flag;
j = k;
}
while(j<sn && s[j]=='*')
j++;
if(j<sn)
flag = -1;
if(flag==-1)
printf("NO\n");
else
printf("YES\n");
}
return 0;
}