UVA148 ZOJ1166 Anagram checker【DFS】

本文介绍了一种用于检测单词或短语是否能通过重新排列字母形成字典中其他单词的算法。该算法读取字典文件和待检测的短语列表,找出所有可能的anagram组合,并确保结果中的单词按字母顺序排列。文章提供了详细的代码实现,包括如何处理输入数据,进行anagram匹配,以及输出结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

It is often fun to see if rearranging the letters of a name gives an amusing anagram. For example, the letters of ‘WILLIAM SHAKESPEARE’ rearrange to form ‘SPEAK REALISM AWHILE’.
    Write a program that will read in a dictionary and a list of phrases and determine which words from the dictionary, if any, form anagrams of the given phrases. Your program must find all sets of words in the dictionary which can be formed from the letters in each phrase. Do not include the set consisting of the original words. If no anagram is present, do not write anything, not even a blank line.
Input
Input will consist of two parts. The first part is the dictionary, the second part is the set of phrases for which you need to find anagrams. Each part of the file will be terminated by a line consisting of a single ‘#’. The dictionary will be in alphabetic order and will contain up to 2000 words, one word per line. The entire file will be in upper case, and no dictionary word or phrase will contain more than 20 letters. You cannot assume the language being used is English.
Output
Output will consist of a series of lines. Each line will consist of the original phrase, a space, an equal sign (=), another space, and the list of words that together make up an anagram of the original phrase, separated by exactly one space. These words must appear in alphabetic sequence.
Sample Input
ABC
AND
DEF
DXZ
K
KX
LJSRT
LT
PT
PTYYWQ
Y
YWJSRQ
ZD
ZZXY

ZZXY ABC DEF
SXZYTWQP KLJ YRTD
ZZXY YWJSRQ PTYYWQ ZZXY

Sample Output
SXZYTWQP KLJ YRTD = DXZ K LJSRT PTYYWQ
SXZYTWQP KLJ YRTD = DXZ K LT PT Y YWJSRQ
SXZYTWQP KLJ YRTD = KX LJSRT PTYYWQ ZD
SXZYTWQP KLJ YRTD = KX LT PT Y YWJSRQ ZD

问题链接UVA148 ZOJ1166 Anagram checker
问题简述:(略)
问题分析
    先给代码暂时不解释。
程序说明:(略)
参考链接:(略)
题记:(略)

AC的C++语言程序如下:

/* UVA148 ZOJ1166 Anagram checker */

#include <bits/stdc++.h>

using namespace std;

const int N = 2000;
const int A = 26;
const int LEN = 20;
string dic[N], s;
int diccnt[N][A], scnt[A], vis[N], k;

struct Word {
    char word[LEN + 1];
} w[LEN];
char t1[LEN + 1], t2[LEN + 1];

int cmp(Word a,Word b)
{
    return strcmp(a.word, b.word) < 0 ? 1 : 0;
}

void dfs(int n, int m)
{
    int cnt = 0;
    for(int i = 0; i < A; i++)
        cnt += scnt[i];

    if(cnt == 0) {
        int cc = 0;
        for(int i = 0; i < m; i++)
            for(int j = 0; j < dic[vis[i]][j]; j++)
                t2[cc++] = dic[vis[i]][j];
        t2[cc] = '\0';
        if(strcmp(t2, t1) == 0) return ;

        cout << s << " =";
        for(int i = 0; i < m; i++)
            cout << " " << dic[vis[i]];
        cout << endl;
    }

    for(int i = n + 1; i < k; i++) {
        bool flag = true;
        for(int j = 0;j<A;j++) {
            scnt[j] -= diccnt[i][j];
            if(scnt[j] < 0)
                flag = false;
        }
        if(flag) {
            vis[m++] = i;
            dfs(i, m);
            m--;
        }
        for(int j = 0; j < A; j++)
            scnt[j] += diccnt[i][j];
    }
}

int main()
{
    k = 0;
    while(cin >> dic[k] && dic[k][0] != '#') {
        memset(diccnt[k], 0, sizeof(diccnt[k]));
        for(int i = 0; dic[k][i]; i++)
            diccnt[k][dic[k][i] - 'A']++;
        k++;
    }
    getchar();

    for(;;) {
        getline(cin, s);
        if(s[0] == '#') break;

        int kk = 0, pos = 0;
        for(int i = 0; s[i]; i++) {
            if(s[i] == ' ') {
                w[kk++].word[pos] = '\0';
                pos = 0;
            } else
                w[kk].word[pos++] = s[i];
        }
        w[kk++].word[pos] = '\0';

        sort(w, w + kk, cmp);

        pos = 0;
        for(int i = 0; i < kk; i++)
            for(int j = 0; w[i].word[j]; j++)
                t1[pos++] = w[i].word[j];

        t1[pos] = '\0';
        memset(scnt, 0, sizeof(scnt));
        for(int i = 0; s[i]; i++)
            if(isupper(s[i]))
                scnt[s[i] - 'A']++;

        dfs(-1, 0);
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值