java字符串排列和组合查找
我正在写一个Android word应用程序。我的代码包含一个方法,该方法将查找长度至少为3的7个字母字符串的字符串和子字符串的所有组合。然后将所有可用的组合与词典中的每个单词进行比较,以找到所有有效的单词。我使用的是递归方法。这是密码java字符串排列和组合查找,java,algorithm,permutation,combinations,Java,Algorithm,Permutation,Combinations,我正在写一个Android word应用程序。我的代码包含一个方法,该方法将查找长度至少为3的7个字母字符串的字符串和子字符串的所有组合。然后将所有可用的组合与词典中的每个单词进行比较,以找到所有有效的单词。我使用的是递归方法。这是密码 // Gets all the permutations of a string. void permuteString(String beginningString, String endingString) { if (endingString.le
// Gets all the permutations of a string.
void permuteString(String beginningString, String endingString) {
if (endingString.length() <= 1){
if((Arrays.binarySearch(mDictionary, beginningString.toLowerCase() + endingString.toLowerCase())) >= 0){
mWordSet.add(beginningString + endingString);
}
}
else
for (int i = 0; i < endingString.length(); i++) {
String newString = endingString.substring(0, i) + endingString.substring(i + 1);
permuteString(beginningString + endingString.charAt(i), newString);
}
}
// Get the combinations of the sub-strings. Minimum 3 letter combinations
void subStrings(String s){
String newString = "";
if(s.length() > 3){
for(int x = 0; x < s.length(); x++){
newString = removeCharAt(x, s);
permuteString("", newString);
subStrings(newString);
}
}
}
//获取字符串的所有排列。
void permuteString(字符串开始字符串、字符串结束字符串){
if(endingString.length()=0){
添加(开始字符串+结束字符串);
}
}
其他的
对于(int i=0;i3){
对于(int x=0;x
上面的代码运行良好,但当我在NexusS上安装它时,我意识到它运行有点太慢了。需要几秒钟才能完成。大约3或4秒,这是不可接受的。
现在我在手机上玩了一些文字游戏,他们会立即计算出字符串的所有组合,这让我相信我的算法不是很有效,可以改进。有人能帮忙吗
公共类三节点{
三节点a、b、c、d、e、f、g、h、i、j、k、l、m、n、o、p、q、r、s、t、u、v、w、x、y、z;
三元组[]儿童={a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z};
private ArrayList words=new ArrayList();
公共无效添加字(字符串字){
添加(word);
}
公共数组列表getWords(){
返回单词;
}
}
公共类Trie{
静态字符串myWord;
静态字符串myLetters=“afinntry”;
静态字符[]myChars;
静态排序;
静态三节点myNode=新三节点();
静态三极电流节点;
静态int y=0;
静态ArrayList availableWords=新ArrayList();
公共静态void main(字符串[]args){
readWords();
getPermutations();
}
公共静态void getPermutations(){
currentNode=myNode;
对于(int x=0;x=myChars.length){
node.addWord(myWord);
//System.out.println(node.getWords()+“”+y);
y++;
返回;
}
if(node.children[myChars[x]-'a']==null){
插入(node.children[myChars[x]-'a']=newtrinode(),myChars,x=x+1);
}否则{
插入(node.children[myChars[x]-'a'],myChars,x=x+1);
}
}
}
使用
而不是测试所有N!可能的情况下,您只能遵循导致结果的前缀树。这将大大减少您要检查的字符串数量。在当前方法中,您要查找每个子字符串的每个排列。因此,对于
“abc”
,您需要查找“abc”
,“acb”
,“bac”
,“bca”
,“cab”
和“cba”
。如果你想找到“排列”的所有排列,你的查找次数几乎是500000000,这是在你还没看过它的子串之前。但是我们可以通过对字典进行预处理,将其缩减为一次查找,而不考虑长度
其思想是将字典中的每个单词放入某种数据结构中,其中每个元素包含一组字符,以及一个包含(仅)这些字符的所有单词的列表。例如,您可以构建一个二叉树,其中有一个节点包含(排序)字符集“abd”
和单词列表[“bad”,“dab”]
。现在,如果我们想找到“dba”
的所有排列,我们将其排序为“abd”
,并在树中查找以检索列表
正如鲍曼所指出的那样,计算机非常适合存储此类数据。trie的优点在于查找时间仅取决于搜索字符串的长度——它与词典的大小无关。由于您将存储相当多的单词,并且大多数搜索字符串都很小(大多数是递归最低级别的3个字符的子字符串),因此这种结构非常理想
在这种情况下,trie中的路径将反映字符集,而不是单词本身。因此,如果您的整个字典都是[“bad”、“dab”、“cab”、“cable”]
,那么您的查找结构最终会是这样的:
在您实现这一点的方式中有一点时间/空间的权衡。在最简单(也是最快)的方法中,每个节点
只包含单词列表和子节点的数组节点[26]
。这允许您通过查看子对象[s.charAt(i)-'a']
(其中s
是您的搜索标准),在固定时间内找到您要查找的子对象
public class TrieNode {
TrieNode a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z;
TrieNode[] children = {a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z};
private ArrayList<String> words = new ArrayList<String>();
public void addWord(String word){
words.add(word);
}
public ArrayList<String> getWords(){
return words;
}
}
public class Trie {
static String myWord;
static String myLetters = "afinnrty";
static char[] myChars;
static Sort sort;
static TrieNode myNode = new TrieNode();
static TrieNode currentNode;
static int y = 0;
static ArrayList<String> availableWords = new ArrayList<String>();
public static void main(String[] args) {
readWords();
getPermutations();
}
public static void getPermutations(){
currentNode = myNode;
for(int x = 0; x < myLetters.length(); x++){
if(currentNode.children[myLetters.charAt(x) - 'a'] != null){
//availableWords.addAll(currentNode.getWords());
currentNode = currentNode.children[myLetters.charAt(x) - 'a'];
System.out.println(currentNode.getWords() + "" + myLetters.charAt(x));
}
}
//System.out.println(availableWords);
}
public static void readWords(){
try {
BufferedReader in = new BufferedReader(new FileReader("c://scrabbledictionary.txt"));
String str;
while ((str = in.readLine()) != null) {
myWord = str;
myChars = str.toCharArray();
sort = new Sort(myChars);
insert(myNode, myChars, 0);
}
in.close();
} catch (IOException e) {
}
}
public static void insert(TrieNode node, char[] myChars, int x){
if(x >= myChars.length){
node.addWord(myWord);
//System.out.println(node.getWords()+""+y);
y++;
return;
}
if(node.children[myChars[x]-'a'] == null){
insert(node.children[myChars[x]-'a'] = new TrieNode(), myChars, x=x+1);
}else{
insert(node.children[myChars[x]-'a'], myChars, x=x+1);
}
}
}
static List<String> permutations(String a) {
List<String> result=new LinkedList<String>();
int len = a.length();
if (len<=1){
result.add(a);
}else{
for (int i=0;i<len; i++){
for (String it:permutations(a.substring(0, i)+a.substring(i+1))){
result.add(a.charAt(i)+it);
}
}
}
return result;
}
public class PermutationString {
private final String innerString;
public PermutationString(String innerString) {
this.innerString = innerString;
}
@Override
public int hashCode() {
int hash = 0x00;
String s1 = this.innerString;
for(int i = 0; i < s1.length(); i++) {
hash += s1.charAt(i);
}
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final PermutationString other = (PermutationString) obj;
int nChars = 26;
int[] chars = new int[nChars];
String s1 = this.innerString;
String s2 = other.innerString;
if(s1.length() != s2.length()) {
return false;
}
for(int i = 0; i < s1.length(); i++) {
chars[s1.charAt(i)-'a']++;
}
for(int i = 0; i < s2.length(); i++) {
chars[s2.charAt(i)-'a']--;
}
for(int i = 0; i < nChars; i++) {
if(chars[i] != 0x00) {
return false;
}
}
return true;
}
}
HashMap<PermutationString,ArrayList<String>> hm = new HashMap<PermutationString,ArrayList<String>>();
String[] dictionary = new String[] {"foo","bar","oof"};
ArrayList<String> items;
for(String s : dictionary) {
PermutationString ps = new PermutationString(s);
if(hm.containsKey(ps)) {
items = hm.get(ps);
items.add(s);
} else {
items = new ArrayList<String>();
items.add(s);
hm.put(ps,items);
}
}
hm.get(new PermutationString("ofo"));
HashMap<PermutationString, ArrayList<String>> hm = new HashMap<PermutationString, ArrayList<String>>();
String[] dictionary = new String[]{"foo", "bar", "oof"};
ArrayList<String> items;
for (String s : dictionary) {
PermutationString ps = new PermutationString(s);
if (hm.containsKey(ps)) {
items = hm.get(ps);
items.add(s);
} else {
items = new ArrayList<String>();
items.add(s);
hm.put(ps, items);
}
}
Assert.assertNull(hm.get(new PermutationString("baa")));
Assert.assertNull(hm.get(new PermutationString("brr")));
Assert.assertNotNull(hm.get(new PermutationString("bar")));
Assert.assertEquals(1,hm.get(new PermutationString("bar")).size());
Assert.assertNotNull(hm.get(new PermutationString("rab")));
Assert.assertEquals(1,hm.get(new PermutationString("rab")).size());
Assert.assertNotNull(hm.get(new PermutationString("foo")));
Assert.assertEquals(2,hm.get(new PermutationString("foo")).size());
Assert.assertNotNull(hm.get(new PermutationString("ofo")));
Assert.assertEquals(2,hm.get(new PermutationString("ofo")).size());
Assert.assertNotNull(hm.get(new PermutationString("oof")));
Assert.assertEquals(2,hm.get(new PermutationString("oof")).size());