Java 我应该如何找到重复的单词序列
我需要检测多个只给出标题的柱状数据块的存在。除了标题词之外,对数据一无所知,每个数据集的标题词都是不同的 重要的是,目前还不知道每个块中有多少单词,因此也不知道有多少块 同样重要的是,单词表总是相对较短——少于20个 因此,给定一个标题词列表或数组,例如:Java 我应该如何找到重复的单词序列,java,algorithm,repeat,Java,Algorithm,Repeat,我需要检测多个只给出标题的柱状数据块的存在。除了标题词之外,对数据一无所知,每个数据集的标题词都是不同的 重要的是,目前还不知道每个块中有多少单词,因此也不知道有多少块 同样重要的是,单词表总是相对较短——少于20个 因此,给定一个标题词列表或数组,例如: Opt Object Type Opt Object Type Opt Object Type 确定它完全由重复序列组成的最有效的处理方式是什么: Opt Object Type 它必须是精确匹配,所以我的第一个想法是搜索[1+],寻找与
Opt
Object
Type
Opt
Object
Type
Opt
Object
Type
确定它完全由重复序列组成的最有效的处理方式是什么:
Opt
Object
Type
它必须是精确匹配,所以我的第一个想法是搜索[1+],寻找与[0]匹配的项,称它们为索引n,m,。。。然后,如果它们是等距的,则检查[1]=[n+1]=[m+1]和[2]=[n+2]=[m+2]等
编辑:它必须适用于某些单词本身在块中重复的单词集,因此
Opt
Opt
Object
Opt
Opt
Object
这是一套2
Opt
Opt
Object
单位序列能包含自己的重复吗?你知道单位序列的长度吗 e、 g 其中,单元顺序为
abcabcdef
如果答案是肯定的,那么你就遇到了一个难题,我认为,除非你知道单元序列的长度(在这种情况下,解决方案很简单,你只需要创建一个状态机,首先存储单元序列,然后验证序列的每个元素其余部分对应于单元序列的每个元素)
如果答案为“否”,则使用此变量识别装置顺序:
Opt
Object
Type
- 初始化指向序列开头的指针P1和P2
- 对于每个新元素,每次递增指针P1,每隔一次递增指针P2(保持一个计数器以执行此操作)
- 如果P1指向P2的一个相同元素,那么您已经找到了一个单位序列
- 现在重复序列的其余部分,以验证它是否包含重复项
更新:您已经澄清了问题,说明单元序列可能包含自身的重复。在这种情况下,使用循环查找算法,但只能保证找到潜在的循环。在整个序列中保持运行,并使用以下状态机,从状态1开始: 状态1:未发现有效的循环;继续找。当循环查找算法找到一个潜在循环时,验证您已经从P获得了一个初步单元序列的2个副本,并进入状态2。如果到达输入的末尾,则转到状态4 状态2:发现初步单元序列。只要循环重复相同,就运行输入。如果到达输入的末尾,则转到状态3。如果发现输入元素与单元序列的对应元素不同,请返回状态1 状态3:如果输入端包含单位序列的完整重复,则输入为单位序列的重复。(如果它在单元序列的中间,例如
abcab
,则找到单元序列,但它不包含完整的重复。)
状态4:未找到单元序列
在我的示例中(重复
abcabcdef
),算法首先找到ABCABC,这将使它处于状态2,它将一直停留在那里,直到它到达第一个DEF,这将使它回到状态1,然后可能在状态1和状态2之间来回跳跃,直到它到达第二个abcabcdef,此时它将重新进入状态2,而在输入结束时它将处于状态3。如果列表由x个重复组组成,每个组包含n个元素
我们知道至少有一个组,所以我们将查看是否有两个重复组,通过比较列表的上半部分和下半部分进行测试
1) 如果以上是真的,我们知道解是一个因子2
2) 如果上面是假的,我们移动到下一个最大的素数,它可以被总字数整除
在每一步中,我们都会检查列表之间是否相等,如果我们找到了,就知道我们有一个包含该因素的解决方案
我们想要返回一个单词列表,对于这些单词,第一个素数的最大因子在子列表中是相等的
因此,我们将上述公式应用于子列表,知道所有子列表都是相等的。。。因此,解决方案最好是递归求解。也就是说,我们只需要孤立地考虑当前的子列表。
该解决方案将是非常有效的,如果加载一个简短的素数表。。。在此之后,有必要计算它们,但如果只考虑几十个素数的列表,那么该列表就必须是非平凡的。我的解决方案可能很幼稚,它可以按预期工作。它的优点是简单
String[] wta; // word text array
...
INTERVAL:
for(int xa=1,max=(wta.length/2); xa<=max; xa++) {
if((wta.length%xa)!=0) { continue; } // ignore intervals which don't divide evenly into the words
for(int xb=0; xb<xa; xb++) { // iterate the words within the current interval
for(int xc=xb+xa; xc<wta.length; xc+=xa) { // iterate the corresponding words in each section
if(!wta[xb].equalsIgnoreCase(wta[xc])) { continue INTERVAL; } // not a cycle
}
}
ivl=xa;
break;
}
String[]wta;//word文本数组
...
间隔时间:
对于(intxa=1,max=(wta.length/2);xa比我的另一个答案更好:一个有效的Java实现,应该简单易懂,并且是通用的:
package com.example.algorithms;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
interface Processor<T> {
public void process(T element);
}
public class RepeatingListFinder<T> implements Processor<T> {
private List<T> unit_sequence = new ArrayList<T>();
private int repeat_count = 0;
private int partial_matches = 0;
private Iterator<T> iterator = null;
/* Class invariant:
*
* The sequence of elements passed through process()
* can be expressed as the concatenation of
* the unit_sequence repeated "repeat_count" times,
* plus the first "element_matches" of the unit_sequence.
*
* The iterator points to the remaining elements of the unit_sequence,
* or null if there have not been any elements processed yet.
*/
public void process(T element) {
if (unit_sequence.isEmpty() || !iterator.next().equals(element))
{
revise_unit_sequence(element);
iterator = unit_sequence.iterator();
repeat_count = 1;
partial_matches = 0;
}
else if (!iterator.hasNext())
{
iterator = unit_sequence.iterator();
++repeat_count;
partial_matches = 0;
}
else
{
++partial_matches;
}
}
/* Unit sequence has changed.
* Restructure and add the new non-matching element.
*/
private void revise_unit_sequence(T element) {
if (repeat_count > 1 || partial_matches > 0)
{
List<T> new_sequence = new ArrayList<T>();
for (int i = 0; i < repeat_count; ++i)
new_sequence.addAll(unit_sequence);
new_sequence.addAll(
unit_sequence.subList(0, partial_matches));
unit_sequence = new_sequence;
}
unit_sequence.add(element);
}
public List<T> getUnitSequence() {
return Collections.unmodifiableList(unit_sequence);
}
public int getRepeatCount() { return repeat_count; }
public int getPartialMatchCount() { return partial_matches; }
public String toString()
{
return "("+getRepeatCount()
+(getPartialMatchCount() > 0
? (" "+getPartialMatchCount()
+"/"+unit_sequence.size())
: "")
+") x "+unit_sequence;
}
/********** static methods below for testing **********/
static public List<Character> stringToCharList(String s)
{
List<Character> result = new ArrayList<Character>();
for (char c : s.toCharArray())
result.add(c);
return result;
}
static public <T> void test(List<T> list)
{
RepeatingListFinder<T> listFinder
= new RepeatingListFinder<T>();
for (T element : list)
listFinder.process(element);
System.out.println(listFinder);
}
static public void test(String testCase)
{
test(stringToCharList(testCase));
}
static public void main(String[] args)
{
test("ABCABCABCABC");
test("ABCDFTBAT");
test("ABABA");
test("ABACABADABACABAEABACABADABACABAEABACABADABAC");
test("ABCABCABCDEFABCABCABCDEFABCABCABCDEF");
test("ABABCABABCABABDABABDABABC");
}
}
package com.example.algorithms;
导入java.util.ArrayList;
导入java.util.Collections;
导入java.util.Iterator;
导入java.util.List;
接口处理器{
公共无效过程(T要素);
}
公共类RepeatingListFinder实现处理器{
私有列表单元_序列=新的ArrayList();
私有整数重复计数=0;
private int partial_matches=0;
私有迭代器迭代器=null;
/*类不变量:
*
*通过进程()的元素序列
*可以表示为
*单元顺序重复“重复计数”次,
*加上单位序列的第一个“元素匹配”。
*
*迭代器指向unit_序列的其余元素,
*如果没有任何元素,则为null