zoukankan      html  css  js  c++  java
  • [luogu2292][L语言]

    题目链接

    思路

    这道题我用的是AC自动机的做法。
    先把子串挂到trie树上,在单词结尾打标记的时候,标记的是当前单词的长度。然后去上面查询母串的时候,每查询到一个单词,就建立一条线段,这条线段的结尾位置是母串当前的位置,开始位置就是用当前位置减去这个单词的长度。
    然后只要去判断,选出一些线段,使得这些线段紧挨着(既不相互覆盖,中间也不遗漏)从母串开始位置铺,能铺到的最远的地方。所以只需要一遍bfs就行了。

    代码

    /*
    * @Author: wxyww
    * @Date:   2018-12-17 08:38:38
    * @Last Modified time: 2018-12-17 09:09:28
    */
    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cmath>
    #include<ctime>
    #include<bitset>
    #include<cstring>
    #include<queue>
    using namespace std;
    typedef long long ll;
    const int N = 2000000 + 100;
    ll read() {
       ll x=0,f=1;char c=getchar();
       while(c<'0'||c>'9') {
          if(c=='-') f=-1;
          c=getchar();
       }
       while(c>='0'&&c<='9') {
          x=x*10+c-'0';
          c=getchar();
       }
       return x*f;
    }
    int trie[1000][30],end[1000];
    char s[30];
    int tot;
    void insert() {
       int len = strlen(s + 1);
       int now = 0;
       for(int i = 1;i <= len;++i) {
          int k = s[i] - 'a';
          if(!trie[now][k]) trie[now][k] = ++tot;
          now = trie[now][k];
       }
       end[now] = len;
    }
    struct node {
       int l,r;
    }e[N];
    int ejs;
    int fail[N];
    char S[N];
    queue<int>q;
    void build() {
       for(int i = 0;i < 26;++i) if(trie[0][i]) q.push(trie[0][i]);
       while(!q.empty()) {
          int u = q.front();q.pop();
          for(int i = 0;i < 26;++i) {
             if(trie[u][i]) fail[trie[u][i]] = trie[fail[u]][i],q.push(trie[u][i]);
             else trie[u][i] = trie[fail[u]][i];
          }
       }
    }
    vector<int>v[N];
    void work() {
       int len = strlen(S + 1);
       ejs = 0;int now = 0;
       for(int i = 1;i <= len;++i) {
          now = trie[now][S[i] - 'a'];
          for(int j = now;j;j = fail[j]) {
             if(end[j]) e[++ejs].l = i - end[j] + 1,e[ejs].r = i;
          }
       }
    }
    int vis[N];
    void bfs() {
       q.push(1);
       int ans = 0;
       for(int i = 1;i <= ejs;++i) v[e[i].l].push_back(i);
       memset(vis,0,sizeof(vis));
       while(!q.empty()) {
          int l = q.front();q.pop();
          int k = v[l].size();
          for(int i = 0;i < k;++i) {
             int z = v[l][i];
             if(vis[z]) continue;
             vis[z] = 1;
             q.push(e[z].r + 1);
             ans = max(ans,e[z].r);
          }
       }
       printf("%d
    ",ans);
       int len = strlen(S + 1);
       for(int i = 1;i <= len;++i) v[i].clear();
    }
    int main() {
       int n = read(),m = read();
       for(int i = 1;i <= n;++i) {
          scanf("%s",s + 1);
          insert();
       }
       build();
       for(int i = 1;i <= m;++i) {
          scanf("%s",S + 1);
          work();
       bfs();
       }
    
       return 0;
    }
    
  • 相关阅读:
    Hbase实用技巧:全量+增量数据的迁移方法
    求职时这样回答问题你就输了!来自IT类面试官视角的深度解读
    云原生2.0时代:开启应用定义基础设施新时代
    让“物”能说会道,揭晓华为云IOT黑科技
    API生态的发展与机遇:从5000组数据看中国API生态与开发者现状
    如何实现微服务架构下的分布式事务?
    Win32可执行文件的开发过程 Win32汇编语言008
    鱼C加密程序 零基础入门学习Delphi10
    Win32可执行文件的开发过程 Win32汇编语言008
    使用MASM01 Win32汇编语言009
  • 原文地址:https://www.cnblogs.com/wxyww/p/10129813.html
Copyright © 2011-2022 走看看