题目:给你一些字符串,问哪些字符串不是其他字符串的子集,字符串的集合为字母组成的重集。
分析:字符串,dancing-links。Knuth有一篇关于dancing-links的论文,讲述关于搜索的优化。
在搜索时,将所有的状态建立一个链表,表之间的状态建立相互关系。
每次搜索时,进行剪枝,将不成立的节点从链表中删掉,回溯时在拼上去。
用数组建立链表,高效方便,存储L,R左右两端下标即可。
本题直接进行删除即可。
如果,一个字符串的补集是另一个字符串的子集,这个字符串的集合一定是另一的超集。
解法:
1.对每个字符串求补集(每个字符的个数记成负的即可)。
2.对补集排序,然后向后扫描,扫到他的子集(补集的超级)就删除那个节点。
3.重新排序,输出。
说明:看到有人用字典树做的,每次插入的时候先查询。
#include <algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> typedef struct noded { char word[11]; int used; }dnode; dnode s[15005]; int L[15005]; int R[15005]; int id[15005]; int sum[15005][27]; using namespace std; int cmp1( const void* a, const void* b ) { int l1 = strlen(((dnode *)a)->word); int l2 = strlen(((dnode *)b)->word); if ( l1 == l2 ) return strcmp( ((dnode *)b)->word, ((dnode *)a)->word ); return l2 - l1; } int cmp2( const void* a, const void* b ) { if ( ((dnode *)b)->used == ((dnode *)a)->used ) return strcmp( ((dnode *)a)->word, ((dnode *)b)->word ); return ((dnode *)a)->used - ((dnode *)b)->used; } int main() { int count = 1; while ( gets(s[count].word) ) { if ( !strlen(s[count].word) ) break; s[count ++].used = 0; } qsort( s+1, count-1, sizeof(s[0]), cmp1 ); memset( sum, 0, sizeof(sum) ); for ( int i = 1 ; i < count ; ++ i ) for ( int j = 0 ; s[i].word[j] ; ++ j ) sum[i][s[i].word[j]-'a'] --; for ( int i = 1 ; i < count ; ++ i ) { id[i] = i; L[i] = i-1; R[i] = i+1; } R[0] = 1; R[count-1] = 0; for ( int p = R[0] ; p ; p = R[p] ) for ( int q = R[p] ; q ; q = R[q] ) { int flag = 1; for ( int k = 0 ; k < 26 ; ++ k ) if ( sum[id[p]][k] > sum[id[q]][k] ) { flag = 0; break; } if ( flag ) { s[id[q]].used = 1; R[L[q]] = R[q]; L[R[q]] = L[q]; } } qsort( s+1, count-1, sizeof(s[0]), cmp2 ); for ( int i = 1 ; i < count ; ++ i ) if ( s[i].used ) break; else printf("%s\n",s[i].word); //system("pause"); return 0; }
UVa 10745 - Dominant Strings,布布扣,bubuko.com
原文地址:http://blog.csdn.net/mobius_strip/article/details/27493645