问题:新单词接龙。
规则:
(1)单词变换:单词Wi添加一个字母,删除一个字母或修改一个字母可以得到单词Wi+1;
(2)字典序接龙:W1,W2,W3....Wn,满足字典序。
将所有单词存在hash表或者Trie树中,然后判断一个单词能否通过变换得到另一个单词,如果能够,则连边。得到的是一个DAG图,做图上最长路径即可。
#include <iostream> #include <cstdlib> #include <cstdio> #include <string> #include <cstring> #include <cmath> #include <vector> #include <queue> #include <algorithm> #include <map> #include <stack> using namespace std; const int maxn = 100003; const int maxd = 20; struct Edge { int v, next; }edge[maxn*4]; int cnt; int first[maxn]; void read_graph(int u, int v) { edge[cnt].v = v; edge[cnt].next = first[u], first[u] = cnt++; } typedef char State[17]; typedef unsigned long UL; State st[maxn]; struct Hash { int first[maxn]; int next[maxn]; void init() { memset(first, -1, sizeof(first)); } int ELFhash(char *key) { UL h = 0; while(*key) { h = (h<<4) + *key++; UL g = h & 0xf0000000L; if(g) h ^= g>>24; h &= ~g; } return h%maxn; } int insert(int s) { int h = ELFhash(st[s]); next[s] = first[h]; first[h] = s; } int find(char *s) { int h = ELFhash(s); for(int u = first[h]; ~u; u = next[u]) { if(strcmp(s, st[u]) == 0) return u; } return -1; } }ha; void change(char *s1, int u) { char s2[maxd]; int len = strlen(s1); memcpy(s2, s1, sizeof(s1)); for(int i = 0; i < len; i++) { for(char j = 'a'; j <= 'z'; j++) { char t = s2[i]; s2[i] = j; int v = ha.find(s2); if(v >= 0) read_graph(u, v); s2[i] = t; } } } void add(char *s1, int u) { char s2[maxd]; int len = strlen(s1); for(int i = 0; i <= len; i++) { for(char j = 'a'; j <= 'z'; j++) { memcpy(s2, s1, sizeof(s1)); for(int k = len; k >= i; k--) { s2[k+1] = s2[k]; } s2[i] = j; int v = ha.find(s2); if(v >= 0) read_graph(u, v); } } } void del(char *s1, int u) { char s2[maxd]; int len = strlen(s1); for(int i = 0, j = 0; i < len; i++) { int k = 0; for(int j = 0; j < len; j++) if(i != j) s2[k++] = s1[j]; s2[k] = '\0'; int v = ha.find(s2); if(v >= 0) read_graph(u, v); } } void init() { cnt = 0; memset(first, -1, sizeof(first)); } int d[maxn]; bool vis[maxn]; int dp(int u) { int &ans = d[u]; if(vis[u]) return ans; vis[u] = 1; ans = 1; for(int e = first[u]; e != -1; e = edge[e].next) { int v = edge[e].v; if(strcmp(st[u], st[v]) < 0) ans = max(ans, dp(v)+1); } return ans; } int n; int main() { char s1[maxd], s2[maxd]; n = 0; init(); ha.init(); while(~scanf("%s", st[n]) && strcmp(st[n], "@END@")) { ha.insert(n); n++; } for(int i = 0; i < n; i++) { change(st[i], i); del(st[i], i); add(st[i], i); } int ans = 0; memset(vis, 0, sizeof(vis)); for(int i = 0; i < n; i++) ans = max(ans, dp(i)); printf("%d\n", ans); system("pause"); }