uva 1519 Dictionary Size

题意:有一个字典,字典有很多单词,要求组合成新词,新词必须来源于原字典,或者由原词的非空前缀和非空后缀组成。

思路:建立trie树,则可以求出不同的前缀和后缀有多少个,但是直接相乘并不是答案,考虑有可能重复的,如XXXAXXX,则A可以选前缀和后缀各一次,XXXA、XXX或者XXX、XXXA,则应该减去。

现在考虑普遍情况,XXXbbb,bbbXXX,若只考虑重复b的情况,假设左边x个b,右边y个b,不考虑重复情况左边应为(1+x)选择,右边应为(1+y)选择,则总共应有这么(1+x)*(1+y)多种情况,但是实际情况应该只有1+x+y种情况,(b的数量,X为任意字符),则应该减去x*y种情况。

还有一个要注意的是如果出现单独的字符,应该标记,建立trie树的时候,不会把单个字符算进去。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define mem(name,value) memset(name,value,sizeof(name))
#define FOR(i,n) for(int i=1;i<=n;i++)
using namespace std;
const int maxn = 400000+5;
const int sigma_size = 26;
struct Trie{
    int ch[maxn][sigma_size];
    int cnt[sigma_size];
    int sz;
    int init(){
        mem(ch[0],0); mem(cnt,0);
        sz = 1;
    }
    int idx(char c){return c-'a';}
    void insert(const char *s){
        int n = strlen(s),u=0;
        for(int i=0;i<n;i++){
            int c = idx(s[i]);
            if(!ch[u][c]){
                mem(ch[sz],0);
                ch[u][c] = sz++;
                if(i) cnt[c]++;
            }
            u = ch[u][c];
        }
    }
}pre,suf;
char s[100];
bool vis[26];
int main(){
    //freopen("in.txt","r",stdin);
    int n;
    while(scanf("%d",&n)==1){
        mem(vis,false);
        pre.init(); suf.init();
        for(int i=0;i<n;i++){
            scanf("%s",s);
            if(strlen(s)==1) vis[s[0]-'a']=1;
            pre.insert(s);
            reverse(s,s+strlen(s));
            suf.insert(s);
        }
        long long ans = (long long)(pre.sz-1)*(suf.sz-1);
        for(int i=0;i<sigma_size;i++) ans -= (long long)pre.cnt[i]*suf.cnt[i];
        for(int i=0;i<sigma_size;i++) if(vis[i]) ans++;
        printf("%lld\n",ans);
    }
    return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值