/*
即每个结点有多个儿子结点。。。然后单词的前缀会在树中重合,
而结点的数据域随题目而变,例如这题,数据域prefixNum表示含以该结点结尾的前缀的单词的个数。
那么如果你想知道树中某单词是否存在,则数据域isWord == 1表示存在以该结点结尾的单词
字典树效率高在于他只需要遍历该单词
*/
#include <iostream>
using namespace std;
struct Node
{
struct Node *child[26];
int perfixNum;//表示含以该结点结尾的前缀的单词的个数
};
Node *root;
void Init()//初始化
{
root = new Node;
for (int i = 0; i < 26; i++)
{
root->child[i] = NULL;
}
}
//插入
void Insert(char word[])
{
int len = strlen(word);
Node *pNode = root;
for (int i = 0; i < len; i++)
{
if (pNode->child[word[i] - 'a'] == NULL)
{
//不存在该结点,则创建一个
Node *newNode = new Node;
newNode->perfixNum = 1;
for (int j = 0; j < 26; j++)
{
newNode->child[j] = NULL;
}
pNode->child[word[i] - 'a'] = newNode;
}
else
{
pNode->child[word[i] - 'a']->perfixNum++;
}
pNode = pNode->child[word[i] - 'a'];
}
}
//查找,通过遍历该单词到该单词的结尾结点的prefixNum就是答案了
int Find(char word[])
{
int len = strlen(word);
Node *pNode = root;
int i;
for (i = 0; i < len; i++)
{
if (pNode->child[word[i] - 'a'] != NULL)
{
pNode = pNode->child[word[i] - 'a'];
}
else
{
break;
}
}
if (i == len)
{
return pNode->perfixNum;
}
else
{
return 0;
}
}
int main()
{
char word[15], prefixWord[15];
Init();
while (gets(word), word[0] != 0)
{
Insert(word);
}
while (gets(prefixWord) != NULL)
{
printf("%d\n", Find(prefixWord));
}
return 0;
}
Phone List
// Trie 基础模板
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <stack>
#include <iostream>
#define Max 100000
#define sigma_size 10
using namespace std;
int ch[Max][sigma_size];
bool val[Max];
int cnt;
char str[10002];
int idx(char c)
{
return c-'0';
}
bool insert(char *s)
{
int i,n=strlen(s);
int c,u=0;
for(i=0;i<n;i++)
{
c=idx(s[i]);
if(!ch[u][c])
{
memset(ch[cnt],0,sizeof(ch[cnt]));
val[cnt]=false;
ch[u][c]=cnt++;
}
if(val[u]) return false;
u=ch[u][c];
}
val[u]=true;
for(i=0;i<sigma_size;i++) //做题时开始忘记这、错了下
if(ch[u][i]) return false;
return true;
}
int main()
{
int T;
int n,i;
scanf("%d",&T);
bool flag;
while(T--)
{
flag=true;
val[0]=0;
memset(ch[0],0,sizeof(ch[0]));
cnt=1;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%s",str);
if(!insert(str))
flag=false;
}
if(flag)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
Flying to the Mars
/*
题目大意:
给你一堆士兵的等级,等级高的的士兵可以当等级小的士兵的师傅,
一个士兵最多一个师傅(可以没有),一个师傅最多1个徒弟(可以没有),如果是师徒关系,
可以用一把扫帚练习技能,问你如果全部士兵都用过扫帚练习时最小需要的扫帚数量。
解题思路:
实质就是字典树的应用。如果所有士兵等级都不同,则就可以用一条师徒链,
所以就需要一把扫帚,而如果出现2个相同等级的士兵,则需要开辟另外一条师徒链,
以此类推,发现只要求出等级相同的最多士兵数,就需要多少把扫帚。
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct Trie
{
int cnt;
Trie *child[10];
Trie(){cnt=0;memset(child,NULL,sizeof(child));}
}*root;
int ans;
void insert(char *s)
{
int id;
Trie *p=root;
for(int i=0;s[i];)
{
id=s[i]-'0';
if(!p->child[id])
p->child[id]=new Trie();
p=p->child[id];
++i;
}
p->cnt++;
ans=max(ans,p->cnt);
}
int main()
{
char s[35];
int n,pos;
for(;~scanf("%d",&n);)
{
ans=0;
root=new Trie();
for(int i=0;i<n;++i)
{
scanf("%s",s);
pos=0;
for(;s[pos]=='0';++pos);
insert(s+pos);
}
printf("%d\n",ans);
}
return 0;
}
魔咒词典
#include<cstdio>
#include<algorithm>
using namespace std;
char str[130];//数据读入所用
char moz[101000][30];//魔咒
char func[101000][90];//对应功能
char Result[130];//结果
int val[101000];//对魔咒排序所用
int vafun[101000];//对功能排序所用
int tot=0;//魔咒总个数
bool cmp(int a,int b){//快排魔咒(从小到大,可也以从大到小,看自己喜欢)
if(strcmp(moz[a],moz[b])==-1) return true;
return false;
}//可以直接写成return strcmp(moz[a],moz[b])==-1;
bool _cmp(int a,int b){//对功能排序
if(strcmp(func[a],func[b])==-1) return true;
return false;
}//return strcmp(func[a],func[b])==-1;
bool Finda(char *s){//二分查找魔咒
int left=0,right=tot-1,mid;
while(left<=right){
mid=(left+right)>>1;//mid=(left+right)/2;
if(!strcmp(moz[val[mid]],s)){
strcpy(Result,func[val[mid]]);//把功能复制给结果Result
return true;//返回
}else if(strcmp(moz[val[mid]],s)==1){
right=mid-1;
}else left=mid+1;
}
return false;
}
bool Findb(char *s){//十分查找功能
int left=0,right=tot-1,mid;
while(left<=right){
mid=(left+right)>>1;
if(!strcmp(func[vafun[mid]],s)){
strcpy(Result,moz[vafun[mid]]+1);
int len=strlen(moz[vafun[mid]]);
Result[len-2]='\0';
return true;
}else if(strcmp(func[vafun[mid]],s)==1){
right=mid-1;
}else left=mid+1;
}
return false;
}
int main(){
int i,Q,len;
bool flag;
while(gets(str),str[0]!='@'){
len=strlen(str);
for(i=0;str[i];i++){//存入魔咒
moz[tot][i]=str[i];
if(str[i]==']') break;
}
moz[tot][++i]='\0';
val[tot]=tot;
strcpy(func[tot],str+i+1);//存入功能
func[tot][len-i-1]='\0';
vafun[tot]=tot++;
}
sort(val,val+tot,cmp);
sort(vafun,vafun+tot,_cmp);
scanf("%d",&Q);
getchar();
while(Q--){
gets(str);
if(str[0]=='['){
flag=Finda(str);
if(flag==false) puts("what?");
else puts(Result);
}else{
flag=Findb(str);
if(flag==false) puts("what?");
else puts(Result);
}
memset(Result,0,sizeof(Result));
}
return 0;
}
确定比赛名次
/*
简单拓扑排序问题,问题在于选取入度为零的点。
*/
#include <stdio.h>
#define MAX 505
#include <string.h>
int map[MAX][MAX], N, M, hash[MAX];
void update( int x )
{
for( int i= 1; i<= N; ++i )
{
map[x][i]= 0;
}
}
void Tsort( )
{
for( int i= 1; i<= N; ++i )
{
for( int j= 1; j<= N; ++j )
{
if( hash[j] )
{
continue;
}
int sign= 1;
for( int k= 1; k<= N&& sign; ++k )
{
if( map[k][j] )
{
sign= 0;
break;
}
}
if( sign )
{
printf( i== 1? "%d": " %d", j );
hash[j]= 1;
update( j );
break;
}
}
}
puts( "" );
}
int main( )
{
while( scanf( "%d%d", &N, &M )!= EOF )
{
memset( map, 0, sizeof( map ) );
memset( hash, 0, sizeof( hash ) );
for( int i= 1; i<= M; ++i )
{
int x, y;
scanf( "%d%d", &x, &y );
map[x][y]= 1;
}
Tsort( );
}
return 0;
}
产生冠军
#include <stdio.h>
#include <string.h>
#define MAXN 1005
int n, top_name, indegree[MAXN];
char name[MAXN][15];
void Init(){
top_name = 0;
memset(indegree, 0, sizeof(indegree));
}
int find_str(char *s){
int i;
for(i=0; i<top_name; i++){
if(strcmp(name[i], s) == 0) break;
}
if(i==top_name){
strcpy(name[top_name++], s);
}
return i;
}
int main(){
int i, k, cnt, pos1, pos2;
char s1[15], s2[15];
while(scanf("%d", &n) == 1 && n){
Init();
for(i=0; i<n; i++){
scanf("%s %s", s1, s2);
pos1 = find_str(s1), pos2 = find_str(s2);
indegree[pos2]++;
}
cnt = 0;
for(i=0; i<top_name; i++){
if(indegree[i] == 0){k = i; cnt++;}
if(cnt > 1) break;
}
if(cnt == 1) printf("Yes\n");
else printf("No\n");
}
return 0;
}
Box Relations
/*
把一个箱子分成三个面,即X,Y,Z
拿X来说,把这个面分为上下两部分,上面记为1,下面记为1+n,当读入X A B条件的时候,
那么A箱的下表面和B箱的上表面构成关系,虽然题目中说是A要比B小,
但是由于我们最后记录的时候i是从小到大来的,所以我们把A放在B的上面,结果是A的坐标比B小
当读入I A B的时候,那么A箱的上表面大于B箱的下表面,B箱的上表面要大于A箱的下表面,
在纸上画个图就很好理解了,接下来就是分成X,Y,Z三个面分别拓扑就好
*/
#include <cstdio>
#include <cstring>
using namespace std;
const int N=2010;
bool g[3][N][N];
int ind[3][N],n;
int topo[3][N];
int x[N],y[N],z[N];
bool toposort(int k)
{
memset(ind[k],0,sizeof(ind[k]));
for(int v=1;v<=n;v++)
for(int u=1;u<=n;u++)
if(g[k][u][v]) ind[k][v]++;
for(int i=0;i<n;i++)
{
int u;
for(u=1;u<=n;u++)
if(ind[k][u]==0) break;
if(u>n) return false;
topo[k][i]=u; ind[k][u]--;
for(int v=1;v<=n;v++)
if(g[k][u][v]) ind[k][v]--;
}
return true;
}
int main()
{
int m,C=0;
while(scanf("%d%d",&n,&m),n||m)
{
memset(g,0,sizeof(g));
for(int i=0;i<3;i++)
for(int u=1;u<=n;u++) g[i][u][u+n]=1;
while(m--)
{
char op[2];
int u,v;
scanf("%s%d%d",op,&u,&v);
if(op[0]=='I')
{
for(int i=0;i<3;i++)
g[i][v][u+n]=g[i][u][v+n]=1;
}
else
{
int k=op[0]-'X';
g[k][u+n][v]=1;
}
}
n*=2;
bool flag=true;
for(int i=0;flag&&i<3;i++)
if(!toposort(i)) flag=false;
n/=2;
if(flag)
{
printf("Case %d: POSSIBLE\n",++C);
for(int i=0;i<2*n;i++)
x[topo[0][i]]=y[topo[1][i]]=z[topo[2][i]]=i;
for(int i=1;i<=n;i++)
printf("%d %d %d %d %d %d\n",x[i],y[i],z[i],x[i+n],y[i+n],z[i+n]);
}
else printf("Case %d: IMPOSSIBLE\n",++C);
printf("\n");
}
return 0;
}
Entropy
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <queue>
using namespace std;
const int MAXN = 1010;
struct node
{
int data;
int dep;
node *L, *R;
node()
{
data = 0;
dep = 0;
L = NULL;
R = NULL;
}
bool operator <(node a) const
{
return a.data < data;
} //重载小于号
};
int ans;
char str[MAXN];
int huf[MAXN];
priority_queue<node> Q;
void BuildHuffman()
{
node *p, *q, *T;
while(Q.size() != 1)
{
p = new node();
q = new node();
T = new node();
*p = Q.top(); Q.pop();
*q = Q.top(); Q.pop();
T->data = p->data + q->data;
T->L = p, T->R = q;
Q.push(*T);
}
return ;
}
queue<node> q;
void solve()
{
node root;
root = Q.top(); Q.pop();
root.dep = 0;
q.push(root);
while(!q.empty())
{
node x = q.front(); q.pop();
if(x.L)
{
x.L->dep = x.dep + 1;
q.push(*(x.L));
}
if(x.R)
{
x.R->dep = x.dep + 1;
q.push(*(x.R));
}
if(!x.L && !x.R)
{
ans += x.dep * x.data;
}
}
}
/*void dfs(node *p, int dep)
{
if(!p->L && !p->R)
{
ans += p->data * dep;
}
if(p->L)
{
dfs(p->L, dep+1);
}
if(p->R)
{
dfs(p->R, dep+1);
}
}*/
void init()
{
ans = 0;
while(!Q.empty()) Q.pop();
while(!q.empty()) q.pop();
memset(huf, 0, sizeof(huf));
}
int main()
{
while(scanf("%s", str) && strcmp(str, "END"))
{
init();
int len = strlen(str);
for(int i = 0; str[i]; i++)
{
huf[str[i]]++;
}
for(int i = 0; i < 100; i++) if(huf[i])
{
node t;
t.data = huf[i];
Q.push(t);
}
if(Q.size() == 1) //特判
{
printf("%d %d 8.0\n", len*8, len);
continue;
}
BuildHuffman();
solve();
//dfs(root, 0); 用DFS也可以实现
printf("%d %d %.1lf\n", len*8, ans, len*8.0/ans);
}
return 0;
}