列表

详情


NC50359. 文本生成器

描述

JSOI交给队员ZYX一个任务,编制一个称之为「文本生成器」的电脑软件:该软件的使用者是一些低幼人群,他们现在使用的是GW文本生成器v6版。该软件可以随机生成一些文章――总是生成一篇长度固定且完全随机的文章——也就是说,生成的文章中每个字节都是完全随机的。如果一篇文章中至少包含使用者们了解的一个单词,那么我们说这篇文章是可读的(我们称文章a包含单词b,当且仅当单词b是文章a的子串)。
但是,即使按照这样的标准,使用者现在使用的GW文本生成器v6版所生成的文章也是几乎完全不可读的。ZYX需要指出GW文本生成器v6生成的所有文本中可读文本的数量,以便能够成功获得v7更新版。你能帮助他吗?

输入描述

输入的第一行包含两个正整数,分别是使用者了解的单词总数N,GW文本生成器v6生成的文本固定长度M;
以下N行,每一行包含一个使用者了解的单词。

输出描述

一个整数,表示可能的文章总数。只需要知道结果模10007的值。

示例1

输入:

2 2
A
B

输出:

100

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

Java(javac 1.8) 解法, 执行用时: 588ms, 内存消耗: 44916K, 提交时间: 2021-03-07 20:06:17

import java.io.*;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.locks.LockSupport;

public class Main {

    static class Task {


        public int[] tn(int a){
            int f[] = new int[11];
            if(a==0) {
                return new int[2];
            }
            int p = 1;
            while(a>0){
                int w = a%10;
                f[p++] = w;
                a/=10;
            }
            return Arrays.copyOf(f,p);
        }

        public int[] tt(String a){
            int f[] = new int[2010];
            int p = 1;

            for(int i=a.length()-1;i>=0;--i) {
                f[p++] = a.charAt(i)-'0';
            }
            return Arrays.copyOf(f, p);
        }



        static int rt = 0;
        static int ch[][] ;
        static int fa[];
        static int id[];
        static int mk[];
        static int ct = 1;
        static int cnt[];

        static void insert(String s,int j,int num) {
            int p = 0; // root
            for (char c : s.toCharArray()) {
                int d = c - 'A';
                if (ch[p][d] == 0) {
                    ch[p][d] = ct++;
                }
                p = ch[p][d];
              //  mk[p]+= num;
            }
            mk[p] = 1;
            id[p] = j;
        }
        static int q[] ;
        static void build(){

            int s = 0; int e = 0;

            for(int i=0;i<26;++i) {
                if(ch[0][i]>0) {
                    q[e++] = ch[0][i];
                }
            }

            while(s<e){
                int c = q[s++];

                if(id[fa[c]]>0){
                    id[c] = id[fa[c]];
                }

                for(int j=0;j<26;++j){
                    if(ch[c][j]>0){
                        fa[ch[c][j]] = ch[fa[c]][j];
                        q[e++] = ch[c][j];
                    }else{
                        ch[c][j] = ch[fa[c]][j];
                    }
                }
            }
//            for(int i=e-1;i>=0;--i){
//                if(id[q[i]]!=-1){
//                    cnt[id[q[i]]] += mk[q[i]];
//                }
//                mk[fa[q[i]]] += mk[q[i]];
//            }
        }
        static int search(String s){
            int at = 0;
            int cnt = 0;
            for(char c:s.toCharArray()){
                int to = c-'a';
                to = ch[at][to];
                int j = to;

                while(j != 0) {
                    cnt += mk[to];
                    j = fa[j];
                }
            }
            return cnt;
        }




        public void solve(int testNumber, InputReader in, PrintWriter out) {

            int t = 1;
            for(int i=0;i<t;++i){


                int n = in.nextInt();
                int m = in.nextInt();
                rt = 0;

                ct = 1;

                cnt  = new int[n];
                String s[] = new String[n];
                int tot = 0;
                Map<String,Integer> mp = new HashMap<>();

                Map<String,Integer> cf = new HashMap<>();
                int ids = 0;
                String ss[] = new String[n];
                for(int j=0;j<n;++j){
                    s[j] = in.next();
                    if(mp.containsKey(s[j])){
                        cf.put(s[j],cf.get(s[j])+1);
                    } else {
                        ss[ids] = s[j];
                        mp.put(s[j],ids++);
                        tot += s[j].length();
                        cf.put(s[j],1);
                    }
                }
                q = new int[tot+1];


                ch = new int[tot+1][26];
                fa = new int[tot+1];
                mk = new int[tot+1];
                id = new int[tot+1];

                Arrays.fill(id,-1);

                for(int j=0;j<ids;++j){
                    insert(ss[j], j+1, cf.get(ss[j]));
                }


                build();
                int at = 0;

               long dp[][][] = new long[m+1][ct][2];

               long mod = 10007;

               dp[0][0][0] = 1;
               for(int j=1;j<=m;++j){
                   for(int lst=0;lst<ct;++lst){
                       for(int k=0;k<26;++k){
                           int to = ch[lst][k];
                           if(id[to]>0){
                               dp[j][to][1] += dp[j-1][lst][0];
                               dp[j][to][1] %= mod;
                               dp[j][to][1] += dp[j-1][lst][1];
                               dp[j][to][1] %= mod;
                           }else{
                               dp[j][to][1] += dp[j-1][lst][1];
                               dp[j][to][1] %= mod;
                               dp[j][to][0] += dp[j-1][lst][0];
                               dp[j][to][0] %= mod;
                           }
                       }
                   }
               }
                long r = 0;
                for(int lst=0;lst<ct;++lst){
                    r += dp[m][lst][1];
                    r %= mod;
                }

               out.print(r);



            }








        }


        static long mul(long a, long b, long p) {
            long res = 0, base = a;

            while (b > 0) {
                if ((b & 1L) > 0)
                    res = (res + base) % p;

                base = (base + base) % p;
                b >>= 1;
            }

            return res;
        }

        static long mod_pow(long k, long n, long p) {
            long res = 1L;
            long temp = k % p;

            while (n != 0L) {
                if ((n & 1L) == 1L) {
                    res = mul(res, temp, p);
                }

                temp = mul(temp, temp, p);
                n = n >> 1L;
            }

            return res % p;
        }


        public static double roundD(double result, int scale) {
            BigDecimal bg = new BigDecimal(result).setScale(scale, RoundingMode.UP);
            return bg.doubleValue();
        }



    }
    private static void solve() {
        InputStream inputStream = System.in;
//                InputStream inputStream  = null;
//                try {
//                    inputStream = new FileInputStream(new File("D:\\chrome_download\\exp.out"));
//                } catch (FileNotFoundException e) {
//                    e.printStackTrace();
//                }
        OutputStream outputStream = System.out;
//                OutputStream outputStream = null;
//                File f = new File("D:\\chrome_download\\");
//                try {
//                    f.createNewFile();
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//                try {
//                    outputStream = new FileOutputStream(f);
//                } catch (FileNotFoundException e) {
//                    e.printStackTrace();
//                }
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        Task task = new Task();
        task.solve(1, in, out);
        out.close();
    }
    public static void main(String[] args) {
        new Thread(null, () -> solve(), "1", (1 << 30)).start();
        // solve();
    }
    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;
        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }
        public String nextLine() {
            String line = null;

            try {
                line = reader.readLine();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

            return line;
        }
        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }

            return tokenizer.nextToken();
        }
        public int nextInt() {
            return Integer.parseInt(next());
        }
        public char nextChar() {
            return next().charAt(0);
        }
        public int[] nextArray(int n) {
            int res[] = new int[n];

            for (int i = 0; i < n; ++i) {
                res[i] = nextInt();
            }

            return res;
        }
        public long nextLong() {
            return Long.parseLong(next());
        }
        public double nextDouble() {
            return Double.parseDouble(next());
        }
    }
}

C++14(g++5.4) 解法, 执行用时: 126ms, 内存消耗: 1000K, 提交时间: 2019-12-14 01:11:03

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 6e4;
const int MOD = 10007;

struct Node {
  int ch[26];
  int fail;
  int val;
};
Node nodes[MAXN];
int sz;
void insert(string s) {
  int cur = 0;
  for (auto ch: s) {
    int id = ch - 'A';
    int &nxt = nodes[cur].ch[id];
    if (nxt == 0) nxt = ++sz;
    cur = nxt;
  }
  nodes[cur].val = true;
}
void build() {
  queue<int> Q; Q.push(0);
  while (!Q.empty()) {
    auto s = Q.front(); Q.pop();
    for (int i = 0; i < 26; i++) {
      int &t = nodes[s].ch[i];
      int f = nodes[s].fail;
      if (t == 0) t = nodes[f].ch[i];
      else {
        while (f && !nodes[f].ch[i]) f = nodes[f].fail;
        nodes[t].fail = !s?0: nodes[f].ch[i];
        nodes[t].val |= nodes[nodes[t].fail].val;
        Q.push(t);
      }
    }
  }
}

int main() {
  int N, M; cin >> N >> M;
  while (N--) {
    string s; cin >> s;
    insert(s);
  }
  build();
  vector<vector<int>> cur(2, vector<int>(sz+1));
  cur[0][0] = 1;
  while (M--) {
    vector<vector<int>> nxt(2, vector<int>(sz+1));
    for (int h = 0; h < 2; h++) {
      for (int s = 0; s <= sz; s++) {
        for (int i = 0; i < 26; i++) {
          int t = nodes[s].ch[i];
          if (nodes[t].val) nxt[1][t] = (nxt[1][t] + cur[h][s]) % MOD;
          else nxt[h][t] = (nxt[h][t] + cur[h][s]) % MOD;
        }
      }
    }
    cur = nxt;
  }
  int tot = 0;
  for (int s = 0; s <= sz; s++) {
    tot = (tot + cur[1][s]) % MOD;
  }
  cout << tot << endl;
}

C++11(clang++ 3.9) 解法, 执行用时: 48ms, 内存消耗: 3304K, 提交时间: 2020-03-05 14:06:31

#include<iostream>
#include<cstdio>
#include<cstring>
#define mod 10007
using namespace std;
int n,m,sz=1,ans1,ans2=1;
int a[6001][27],point[6001],q[6001],f[101][60001];
char s[101];
bool danger[6001];
void ins()
{
	int now=1,c;
	for(int i=0;i<strlen(s);i++)
	{
		c=s[i]-'A'+1;
		if(a[now][c]) now=a[now][c];
		else now=a[now][c]=++sz;
	}
	danger[now]=1;
}
void acmach()
{
	int t=0,w=1,now;
	q[0]=1;point[1]=0;
	while(t<w)
	{
		now=q[t++];
		for(int i=1;i<=26;i++)
		{
			if(!a[now][i]) continue;
			int k=point[now];
			while(!a[k][i]) k=point[k];
			point[a[now][i]]=a[k][i];
			if(danger[a[k][i]])
			danger[a[now][i]]=1;
			q[w++]=a[now][i];
			
		}
	}
}
void dp(int x)
{
	for(int i=1;i<=sz;i++)
	{
		if(danger[i]||!f[x-1][i]) continue;
		for(int j=1;j<=26;j++)
		{
			int k=i;
			while(!a[k][j]) k=point[k];
			f[x][a[k][j]]=(f[x][a[k][j]]+f[x-1][i])%mod;
		}
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=26;i++) a[0][i]=1;
	for(int i=1;i<=n;i++)
	{
		scanf("%s",s);
		ins();
	}
	acmach();
	f[0][1]=1;
	for(int i=1;i<=m;i++) dp(i);
	for(int i=1;i<=m;i++)
	ans2=(ans2*26)%mod;
	for(int i=1;i<=sz;i++)
	if(!danger[i]) ans1=(ans1+f[m][i])%mod;
	printf("%d",(ans2-ans1+mod)%mod);
	return 0;
}

上一题