欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Trie树

程序员文章站 2022-05-19 18:54:59
...

暂时没学懂,先把板子放这吧。

题意:给出一个字符串和S个单词组成的字典,问把这个字符串分解成若干单词的连接,总共有多少种?(单词可重复)

思路:令d[i]表示从字符i开始的字符串的分解方案数,则dans[i]=sum{dans[i+d[x]] | 单词x是S[i…len]的前缀};

#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<vector>
using namespace std;
typedef long long LL;
const int maxn=300010;
const int MOD=20071027;
int d[maxn],len;
vector<int> ans;
struct node
{
    node *next[30];
    int value;
    int num;
    node()
    {
        for(int i=0;i<30;i++)
            next[i]=NULL;
        value=0;
    }
}root;
string a;
int n;
void insert(string s)
{
    node *p=&root;
    int k=0,l=s.size();
    while(k<l)
    {
        if(!p->next[s[k]-'a'])
            p->next[s[k]-'a']=new node;
        p=p->next[s[k]-'a'];
        k++;
    }
    p->value=l;
}
void find(int x)
{
    ans.clear();
    node *p=&root;
    int y=x;
    while(x<len&&p->next[a[x]-'a']!=NULL)
    {
        if(p->next[a[x]-'a']->value)
        ans.push_back(p->next[a[x]-'a']->value);
        p=p->next[a[x]-'a'];
        x++;
    }
}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif
    int t=1;
    string x;
    while(cin>>a)
    {
        cin>>n;
        len=a.size();
        for(int i=0;i<30;i++)
        root.next[i]=NULL;
        for(int i=0;i<n;i++)
        {
            cin>>x;
            insert(x);
        }
        memset(d,0,sizeof(d));
        d[len]=1;
        for(int i=len-1;i>=0;i--)
        {
            find(i);
            for(int j=0;j<ans.size();j++)
            d[i]=(d[i]+d[i+ans[j]])%MOD;
        }
        cout<<"Case "<<t++<<": ";
        cout<<d[0]<<endl;
    }
    return 0;
}

或者直接在find的时候更新d数组

#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long LL;
const int maxn=300010;
const int MOD=20071027;
int d[maxn],len;
struct node
{
    node *next[30];
    int value;
    int num;
    node()
    {
        for(int i=0;i<30;i++)
            next[i]=NULL;
        value=0;
    }
}root;
string a;
int n;
void insert(string s)
{
    node *p=&root;
    int k=0,l=s.size();
    while(k<l)
    {
        if(!p->next[s[k]-'a'])
            p->next[s[k]-'a']=new node;
        p=p->next[s[k]-'a'];
        k++;
    }
    p->value=1;
    p->num++;
}
void find(int x)
{
    node *p=&root;
    int y=x;//cout<<(p->next[a[x]-'a']==NULL)<<endl;
    while(x<len&&p->next[a[x]-'a']!=NULL)
    {
        if(p->next[a[x]-'a']->value)d[y]=(d[y]+d[x+1])%MOD;
        p=p->next[a[x]-'a'];
        x++;
    }
}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif
    int t=1;
    string x;
    while(cin>>a)
    {
        cin>>n;
        len=a.size();
        for(int i=0;i<30;i++)
        root.next[i]=NULL;
        for(int i=0;i<n;i++)
        {
            cin>>x;
            insert(x);
        }
        memset(d,0,sizeof(d));
        d[len]=1;
        for(int i=len-1;i>=0;i--)
            find(i);
        cout<<"Case "<<t++<<": ";
        cout<<d[0]%20071027<<endl;
    }
    return 0;

作者:u010660276
来源:CSDN
原文:https://blog.csdn.net/u010660276/article/details/19678289
版权声明:本文为博主原创文章,转载请附上博文链接!