AC自动机通配符匹配

来源:互联网 发布:数据库双机备份 编辑:程序博客网 时间:2024/05/19 05:32

原文链接:http://blog.csdn.net/waitfor_/article/details/18563709


计算机软件)技术中,通配符可用于代替字符。 通常地,星号“*”匹配0个或以上的字符,问号“?”匹配1个字符。(wiki百科)

今天做Leetcode上的一道题时不会做,网上查到了这么一种做法,当年打比赛的时候都没有碰到过。。。。

Leetcode Wildcard Matching

递归做法TLE

  1. class Solution {  
  2. public:  
  3.     bool isMatch(const char *s, const char *p) {  
  4.         char cs = *s;  
  5.         char cp = *p;  
  6.         if(cp == '\0') {  
  7.             return cs == cp;  
  8.         } else if (cp == '?') {  
  9.             if (cs == '\0'return false;  
  10.             return isMatch(s + 1,p + 1);  
  11.         } else if (cp == '*') {  
  12.             const char *st = s;  
  13.             while(cp == '*'){  
  14.                 p++;  
  15.                 cp = *p;  
  16.             }  
  17.             for(; *st != '\0'; ++st) {  
  18.                 if (isMatch(st, p)) return true;  
  19.             }  
  20.             return isMatch(st,p);  
  21.         } else if (cp != cs)  
  22.             return false;  
  23.         return isMatch(s + 1,p + 1);  
  24.     }  
  25. };  

非递归改改AC

  1. class Solution {  
  2. public:  
  3.     bool isMatch(const char *s, const char *p) {    
  4.         // Start typing your C/C++ solution below    
  5.         // DO NOT write int main() function    
  6.              
  7.         const char* star=NULL;    
  8.         const char* ss=s;     
  9.         while (*s){    
  10.             if ((*p=='?')||(*p==*s)){s++;p++;continue;}    
  11.             if (*p=='*'){star=p++; ss=s;continue;}  //star可以更新,使用贪心法  
  12.             if (star){ p = star+1; s=++ss;continue;}  
  13.             return false;    
  14.         }    
  15.         while (*p=='*'){p++;}    
  16.         return !*p;    
  17.     }    
  18.   
  19. };  
这段代码我参考的http://blog.csdn.net/doc_sgl/article/details/12721187,代码短小精悍,还是知道仔细体会。



HDU 3901
关于AC自动机通配符匹配的相关知识请看点击打开链接

  1. #include<cstdio>  
  2. #include<cstring>  
  3. #include<vector>  
  4. using namespace std;  
  5. #define N 100005  
  6. #define B 26  
  7.   
  8. int tree[N][B],size;  
  9. vector<int> key[N];  
  10. int cnt[N],tcnt;  
  11. void build(char str[]){  
  12.     size=tcnt=0;  
  13.     memset(tree[0],0,sizeof(tree[0]));  
  14.     key[0].clear();  
  15.   
  16.     int node=0;  
  17.     for(int i=0;!i||str[i-1];i++){  
  18.         if(str[i]=='?'||str[i]==0){  
  19.             if(node){  
  20.                 key[node].push_back(i-1);  
  21.                 node=0; tcnt++;  
  22.             }  
  23.             continue;  
  24.         }else{  
  25.             int c=str[i]-'a';  
  26.             if(!tree[node][c]){  
  27.                 tree[node][c]=++size;  
  28.                 memset(tree[size],0,sizeof(tree[size]));  
  29.                 key[size].clear();  
  30.             }  
  31.             node=tree[node][c];  
  32.         }  
  33.     }  
  34. }  
  35.   
  36. int que[N];  
  37. int fail[N];  
  38. void getfail(){  
  39.     int *s=que,*e=que;  
  40.     for(int i=0;i<B;i++){  
  41.         if(tree[0][i]){  
  42.             fail[tree[0][i]]=0;  
  43.             *e++=tree[0][i];  
  44.         }  
  45.     }  
  46.     while(s!=e){  
  47.         int p=*s++;  
  48.         for(int i=0;i<B;i++){  
  49.             if(tree[p][i]){  
  50.                 int v=tree[p][i];  
  51.                 *e++=v;  
  52.                 fail[v]=tree[fail[p]][i];  
  53.                 if(key[fail[v]].size()){  
  54.                     key[v].insert(key[v].end(),  
  55.                             key[fail[v]].begin(),key[fail[v]].end());  
  56.                 }  
  57.             }else{  
  58.                 tree[p][i]=tree[fail[p]][i];  
  59.             }  
  60.         }  
  61.     }  
  62. }  
  63.   
  64. int find(char str[]){  
  65.     if(tcnt==0) return 0;  
  66.     int node=0;  
  67.     for(int i=0;str[i];i++){  
  68.         node=tree[node][str[i]-'a'];  
  69.         cnt[i] = 0;   
  70.         for(int j=0;j<key[node].size();j++){  
  71.             if(i>=key[node][j]){  
  72.                 cnt[i-key[node][j]]++;  
  73.                 if(cnt[i-key[node][j]]==tcnt) return i-key[node][j];  
  74.             }  
  75.         }  
  76.     }  
  77.     return -1;  
  78. }  
  79.   
  80. char tmp[N];  
  81. char src[N];  
  82. char wild[N];  
  83. bool match(int ls, int lp){  
  84.     int tl=0;  
  85.     for(int i=0;i<lp;i++) if(wild[i]!='*') tl++;   
  86.     if(tl>ls) return false;  
  87.   
  88.     int s=-1;  
  89.     for(int i=0;i==0||src[i-1];i++){   //如果最左不是*需要从头开始匹配到第一个*  
  90.         if((src[i]!=0&&wild[i]=='?')||src[i]==wild[i]) continue;  
  91.         if(wild[i]=='*') s=i+1;  
  92.         else return false;  
  93.         break;   
  94.     }  
  95.     if(s==-1) return true;   
  96.       
  97.     for(int i=ls-1,j=lp-1;;i--,j--){   //如果最右不是*需要从结尾开始倒着匹配到倒数第一个*  
  98.         if(i==-1&&j==-1) break;  
  99.         if(i==-1){  
  100.             if(wild[j]!='*'return false;   
  101.             break;  
  102.         }  
  103.         if(j==-1) return false;   
  104.         if(src[i]==wild[j]||wild[j]=='?'){  
  105.             src[ls=i] = wild[j] = 0;  
  106.         } else if(wild[j]=='*'break;  
  107.         else return false;  
  108.     }  
  109.   
  110.     int ts=s-1;  
  111.     for(int i=1;i<lp-tl;i++){       //剩下的部分为*......*将其中每个**中间部分用AC自动机匹配即可  
  112.         if(wild[s]=='*'){s++;continue;}  
  113.         int len = 0;  
  114.         for(;wild[s]!='*'&&wild[s];s++){  
  115.             tmp[len]=wild[s];  
  116.             tmp[++len]=0;  
  117.         }  
  118.         s++;  
  119.         build(tmp);  
  120.         getfail();    //这两步构造AC自动机  
  121.         int pos=find(src+ts);   //寻找最左边匹配位置  
  122.         if(pos==-1) return false;   
  123.         else{  
  124.             ts+=pos+len;  
  125.             if(ts>ls) return false;   
  126.         }  
  127.     }  
  128.     return true;   
  129. }   
  130.   
  131. int main(){  
  132.     while(~scanf("%s", src)){  
  133.         scanf("%s", wild);  
  134.         puts(match(strlen(src), strlen(wild))?"YES":"NO");   
  135.     }  
  136. }  

0 0
原创粉丝点击