病毒侵袭 HDU - 2896(AC自动机求子串包含哪些模式串)

题目链接

题意:给n个模式串,m个待匹配串,每个串中包含哪些模式串打印出来。

思路:主要没有看清不止小写字母导致一直wa。用一个数组记录最后结尾的状态,然后去判断一下就好了。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 6;
int n;
char a[510][210];
namespace AC {
int tr[N][130], tot;
int e[N], fail[N];
int v[N];
void insert(char *s,int w) {
  int u = 0;
  for (int i = 1; s[i]; i++) {
    if (!tr[u][s[i]]) tr[u][s[i]] = ++tot;
    u = tr[u][s[i]];
  }
  e[u]++;
  v[w]=u;
}
queue<int> q;
void build() {
  for (int i = 0; i < 130; i++)
    if (tr[0][i]) q.push(tr[0][i]);
  while (q.size()) {
    int u = q.front();
    q.pop();
    for (int i = 0; i < 130; i++) {
      if (tr[u][i])
        fail[tr[u][i]] = tr[fail[u]][i], q.push(tr[u][i]);
      else
        tr[u][i] = tr[fail[u]][i];
    }
  }
}
int query(char *t,int w) {
  int u = 0, res = 0;
  int k=0;
  set<int > ss;
  for (int i = 1; t[i]; i++) {
    u = tr[u][t[i]];  // 转移
    for (int j = u; j && e[j] != 0; j = fail[j]) {
      if(e[j]>=1)
      {
          ss.insert(j);
      }
    }
  }
  if(ss.empty())
  {
      return 0;
  }
  else
  {
      printf("web %d:",w);
      for(int i=1;i<=n;i++)
      {
          if(ss.count(v[i]))
          {
              printf(" %d",i);
          }
      }
      printf("\n");
  }
}
void init(){
    memset(tr,0,sizeof(tr));
    tot=0;
    memset(fail,0,sizeof(fail));
    memset(e,0,sizeof(e));
    
}
}  // namespace AC
char s[N];
int main() {
    int ans=0;
  scanf("%d", &n);
  for (int i = 1; i <= n; i++) scanf("%s", a[i] + 1), AC::insert(a[i],i);
  int t;
  AC::build();
  scanf("%d",&t);
  for(int i=1;i<=t;i++){
  scanf("%s", s + 1);
  if(AC::query(s,i))
  {
      ans++;
  }
    }
    printf("total: %d\n",ans);
  return 0;
}

 

posted @ 2020-09-24 20:15  Ldler  Views(93)  Comments(0Edit  收藏  举报