题目传送门
问题描述
比赛开始了!在准备比赛的过程中,iSea希望将参赛队伍的名字单独打印在一张纸上。
不幸的是,iSea所能找到的只是一台古老的打印机:古老得让人难以置信,它只有三种操作方式:
●“一个”——“z”:26个字母你可以输入
●“▽”:删除最后一封信如果它存在
●“打印”:打印这个词你输入打印机
打印机刚开始是空的,iSea必须使用这三个操作来打印所有团队的名字,不一定按照输入的顺序。每次,他都可以在打印机的末尾输入字母,或者删除最后一个字母,或者打印当前单词。打印后,字母还在打印机里,你可以删除一些字母来打印下一个,但你不需要删除最后一个单词的字母。
iSea想把总操作次数减到最少,请帮帮他。
输入
输入中有几个测试用例。
每个测试用例开始与一个整数N(1≤N≤10000),表明团队名称的数量。
接下来是N个字符串,每个字符串只包含小写字母,不为空,长度不超过50。
输入以文件标记结束。
输出
对于每个测试用例,输出一个整数,表示最小操作数。
Sample Input
2
freeradiant
freeopen
Sample Output
21
Hint
The sample’s operation is:
f-r-e-e-o-p-e-n-Print-Del-Del-Del-Del-r-a-d-i-a-n-t-Print
操作次数=节点数*2+字符串的个数n-最长的字符串的长度
#include<cstdio>
#include<cstring>
using namespace std;
int cnt,maxn=0;
struct trie
{
trie *nex[26];
trie()
{
for(int i=0;i<26;i++)
nex[i]=NULL;
}
};
trie *root;
void create(char *str)
{
int len=strlen(str);
maxn=maxn>len?maxn:len;
trie *a=root;
for(int i=0;i<len;i++)
{
int ch=str[i]-'a';
if(a->nex[ch]==NULL)
{
a->nex[ch]=new trie();
cnt++; //计数
}
a=a->nex[ch];
}
}
void del(trie *a)
{
for(int i=0;i<26;i++)
if(a->nex[i])
del(a->nex[i]);
delete(a);
}
char s[51];
int main()
{
int n;
while(~scanf("%d",&n))
{
cnt=0,maxn=0;
root=new trie();
for(int i=1;i<=n;i++)
{
scanf("%s",s);
create(s);
}
printf("%d\n",cnt*2+n-maxn);
del(root);
}
}