上个周末给学校新队员上课...很是紧张..周日那场想来现场coding..就是很简单的高精度加法...结果怯场了..还是狐狸大大上来救了我..好丢人~~囧..这一向状态一直怪怪的~~这道题起码卡了三天吧~~其实这三天也是招新各种事~~没多大心思来做题~~昨天晚上终于把这题搞定了~~
题意就是说给一个字典...并同时给出每个单词的出现次数...是想一下手机的输入法...然后按手机的输入一串按键~~每按一下按键输出一个推荐字串~~这个字串是在字典中次数最多的前缀..如果有两个相等的..输出字典序靠前的....如果输入一串按键,在字典里一个也没得.那就只能输出"MANUALLY"...其实感觉这题是很实用很现实的~~咱们平时用手机输入法就是有这个性质~~
这道题还是的字典树...要求的是前缀出现次数最多..每个点的定义:
struct node
{
int s[26],x,father,w;
char c;
}
这道题因为有多组数据..动态分配空间如果不释放又很浪费..释放又很耗时...所以采取了开辟静态空间再来链接的伪指针方式....s[ ] 则是记录起孩子是否能链接到哪个位置...x是记录有多少个单词会经过这个点...所以在构造字典树时..每经过一个点..这个点的x就++...father是记录字典树中每个点的父亲..这里是为了这道题后面的输出方便..w是记录当前点所在层数..同样也是为了后面的处理方便...c是当前点是哪个字符..同样也是为了后面的处理方便....s[ ],father,x,w,c在构造树时都能得到准确的值....
构造树的过程和我上一个日志类似..只是多加几个运算得到father,x,w,c而已了~~就直接看构造完树后怎么得到想要的结果..做的话用一个队列来维护..先是超级头结点0入内..可以想象一下...每一次读一个字符就往下做一层...而队列的目的就是看每一层还有多少点可以进行拓展.....每次读一个字符c..如果不是'1'就继续做...扫描所有还能符合条件的上一层的点..找到他们孩子中即在手机按键上是这个c-'0'又其存在...这种点先入队..然后判断其x值..找到所有孩子中满足条件的点..如果没有一个点能入队代表不存在符合输入信息的前缀了~~就要跳出输出"MANUALLY"...如果能找到最佳前缀...则输出..输出的话就从这个最佳的点开始用father往上走..直到走到father为0..就能得到这个前缀了..
自己在写的时候调了很多bug...整了不少时间才搞定...还是自己队字典树不大熟练吧...囧...
Program:
#include<iostream>
#include<queue>
#define MAXN 1002
using namespace std;
struct node
{
int s[26],x,father,w;
char c;
}a[10001];
int t,T,w,m,i,p[MAXN],l,g,newdata;
int turn[26]={2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,7,8,8,8,9,9,9,9};
char s[MAXN][101],c;
void find(int h,int k)
{
if (k>l) return;
a[h].x+=p[i];
if (!a[h].s[s[i][k]-'a'])
{
g++;
a[h].s[s[i][k]-'a']=g;
a[g].father=h;
a[g].w=k+1;
a[g].c=s[i][k];
if (k==l) a[g].x=p[i]; else a[g].x=0;
}
find(a[h].s[s[i][k]-'a'],k+1);
}
queue<int> myqueue;
void make()
{
int h,k,m,i,step=0;
char s[111];
while (!myqueue.empty()) myqueue.pop();
myqueue.push(0);
while (scanf("%c",&c)!=EOF)
{
if (c=='1') return;
h=myqueue.front();
m=0;
while (a[h].w==step)
{
for (i=0;i<26;i++)
if ((turn[i]==c-'0')&&(a[h].s[i]))
{
myqueue.push(a[h].s[i]);
if (a[a[h].s[i]].x>m)
{
k=a[h].s[i];
m=a[k].x;
}
}
myqueue.pop();
if (myqueue.empty()) break;
h=myqueue.front();
}
if (!m) goto A;
step++;
s[step]='\0';
for (i=step-1;i>=0;i--)
{
s[i]=a[k].c;
k=a[k].father;
}
puts(s);
}
A:
printf("MANUALLY\n");
while (scanf("%c",&c)!=EOF)
{
if (c=='1') return;
printf("MANUALLY\n");
}
return;
}
int main()
{
scanf("%d",&T);
for (t=1;t<=T;t++)
{
scanf("%d",&w);
g=0;
memset(a,0,sizeof(a)); p[0]=0;
for (i=1;i<=w;i++)
{
scanf("%s%d",s[i],&p[i]);
l=strlen(s[i])-1;
find(0,0);
}
printf("Scenario #%d:\n",t);
scanf("%d",&m); a[0].x=0;
while (m--)
{
getchar();
make();
printf("\n");
}
printf("\n");
}
return 0;
}