[一本通1700]PFS集合

題目描述

有一種特殊的集合叫作PFS(Prefix Free Set)集合。ios

一個PFS集合由若干字符串構成,且不存在一個字符串是另外一個字符串的前綴。空集也被看做是PFS集合。spa

例如 {\("hello"\)} 和 {\("hello", "goodbye", "giant", "hi"\)} 是PFS集合,但 {\("hello","hell"\)} 和{\("great","gig","g"\)} 不是。code

如今給你一個集合,請你求出它的子集是PFS集合的子集個數,答案對\(9191\)取模。字符串

輸入

輸入數據第一行一個整數\(n\),表示集合裏元素的個數。get

如下n行,每行一個非空字符串\(s\),僅包含小寫英文字母,表示集合中的元素。數據保證不存在兩個相同的字符串。string

輸出

輸出一個正整數\(ans\),表示對\(9191\)取模後的答案。io

輸入樣例

3
hello
hi
hell

輸出樣例

6

提示

輸入輸出樣例解釋

除了 {\("hell","hello"\)} 和 {\("hi","hello","hell"\)} 兩種狀況外,其他狀況均是PFS集合。class

數據規模

對於\(30%\)的數據,\(n≤20\)
對於\(100%\)的數據,\(1≤n≤50000\),字符串長度不大於\(50\)stream

思路

\(f[i]+=f[ch[i][1]]\times f[ch[i][2]]\times \cdots\times f[ch[i][26]]\)im

代碼

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int N = 2500000 + 128;

int to[N][26];
int p;

int cnt[N];

int f[N];

void dfs(int u)
{
    int ans = 1;
    for (int i = 0; i < 26; i++)
        if (to[u][i])
        {
            dfs(to[u][i]);
            ans = ans * f[to[u][i]] % 9191;
        }
    f[u] = ans;
    if (cnt[u])
        f[u]++;
}

static char str[50016];

int main()
{
    int n;
    scanf(" %d", &n);
    getchar();

    ++p;
    for (int i = 1; i <= n; i++)
    {
        scanf(" %s", str + 1);
        int len = strlen(str + 1);
        int now = 1;
        for (int i = 1; i <= len; i++)
        {
            if (to[now][str[i] - 'a'] == 0)
                to[now][str[i] - 'a'] = ++p;
            now = to[now][str[i] - 'a'];
        }
        cnt[now] = 1;
    }
    dfs(1);

    printf("%d", f[1] % 9191);
    return 0;
}
相關文章
相關標籤/搜索