我有一个无限的字符串。这个字符串的长度在我们的想象中是无限的,并且不能被限制。假设我们有一个像这样的序列字符串:
“123456789 ...”
实际上代表下一个序列的数字9之后的点。所以,它会是这样的:
“... 7891011121314 ...”
在本节中,我想解释一下这个要求。要求是找到第一次出现输入String的索引(称为 n )。让我举个例子:
N = “3”
第一个指数n = 2
N = “910”
第一个指数n = 8
我编写了算法来查找String n 的索引。但是算法只是一个while循环来检查 n 的索引,如果找不到 n 的索引,则逐个添加下一个序列号。我想要一个更好的算法来找到第一次出现的 n 的索引,而不依赖于循环或更少的循环。至少,如果 n 的值很大,则算法的运行时间不会超过2秒(例如:123456790或62716855)。
我的代码片段:
while(!num.contains(s)){
num +=start.toString();
start = start.add(BigInteger.ONE);
}
这是我的完整代码:Full Code of My Code
答案 0 :(得分:3)
以下是如何解决此问题的一般说明。将其翻译为Java仍然具有挑战性。
你的输入字符串基本上是所有自然数的无限序列1 2 3 4 5 6 8 9 10 11 ....
我认为练习的目的是识别子串n
所属的输入字符串的自然数的第一个子序列,然后计算其索引而不实际构造大的"无限"字符串。
为此,您必须尝试将子字符串n
拆分为具有尽可能少的数字的递增序列。
首先,您必须检查子字符串n
是否创建了一个单位数字序列。例如,如果n == 345678(请注意,n可能包含单个数字和双位数字,例如n == 345678910
,您也应该能够识别)。
如果您在该步骤中失败,则应查找一系列双位数字。例如,n == 33343536
就是这种情况。现在,这可能会变得更棘手,因为n == 2333435363
也是两位数的序列,但是序列的前导和尾随数字(32和37)被截断。
如果再次失败,则会查找3位数的序列。
如果您没有找到任何序列,则将整个子字符串n
视为大字符串中的单个数字。
现在,假设n
为199319941995
,您在上一步中发现序列中的第一个数字为1993
。剩下的工作是计算输入String中数字1993
的索引。你知道单位数字需要1 * 9个索引。两位数字表示2 * 90个索引。三位数字表示3 * 900个指数。 1000和1993之间的3位数字需要4 * 993个指数。因此,1993年的索引是1 * 9 + 2 * 90 + 3 * 900 + 4 * 993,这是子串199319941995
的第一个索引。
答案 1 :(得分:2)
使用String
我们可以按照以下方式执行此操作,
String largeValue = "2323254534534642342354346876985374";
String searchValue = "32545345346423423543468769";
if(largeValue.contains(searchValue)){
System.out.println("The index is : "+largeValue.indexOf(searchValue));
}
注意: -
我们只能使用largeValue.indexOf(searchValue)
,如果它返回-1表示searchValue
中不存在largeValue
,否则您将获得特定索引。
答案 2 :(得分:0)
据我了解,您可以使用String.indexOf
方法:
int found = longString.indexOf(searchString);
if(found != -1) System.out.println("Found index is: " + found);
答案 3 :(得分:0)
我的想法是对数据进行统计,其中一种方法是为每个数字(0到9)设置所有索引位置,并根据索引数据进行搜索,因为输入文本很大,搜索速度很快太慢了,所以下面会导致在同一个大文本上快速搜索多个搜索输入:
使用C#的示例: (在Java中使用:
HashMap<K, V> and ArrayList<T> and Character.getNumericValue(c)
)
string input = "................";
Dictionary<int, List<int>> numIndex = new Dictionary<int, List<int>>(10);
for(int index = 0; index < 10; index++)
numIndex.Add(index , new List<int>(20));
for(int charIndex = 0; charIndex < input.Length; charIndex++){
for(int index = 0; index < 10; index++){
int value = Convert.ToInt32(input[charIndex]);
if(value == index)
numIndex[value].Add(charIndex);
}
}
int FindIndex(string nValue){
// nValue = "213654789";
foreach(int indexValue in numIndex[Conver.ToInt32(nValue[0])])
{
if(nValue == input.Substring(indexValue, nValue.Length))
return indexValue; // First Index Value Found
}
return -1;
}
编辑为无限缓冲区添加想法,没有缓冲区关闭检查逻辑的伪代码逻辑,我留给用户添加它:
int charIndex = -1
char charValue
string textValue = "456321587"
char[] textCompare = new char[textValue.Length]
while charValue = charsBuffer.ReadChar()
BEGIN
charIndex = charIndex + 1
if textValue[0] == charValue
BEGIN
int count = 1
textCompare[0] = charValue
while count < textValue.Length
BEGIN
textCompare[count] = charsBuffer.ReadChar()
count = count + 1
END
if textValue == new string(textCompare)
return charIndex
charIndex = charIndex + textValue.Length
END
END
return -1
charsBuffer.ReadChar()可能是一个大文本文件缓冲区或网络文本缓冲区或任何大文本缓冲区
答案 4 :(得分:0)
除了在另一个答案中提到的像Knuth-Morris-Pratt这样的高级算法之外,您还可以使用有限状态机进行字符串匹配。这样做的优点是回溯成本远低于while循环的朴素解决方案,但可以很容易地与标准javas正则表达式一起使用。解决方案是:
CharSequence text = // the long sequence of text
String search = // whatever you want to search
Matcher matcher = Pattern.compile(Pattern.quoute(search)).matcher(text);
matcher.find();
int startIndex = matcher.match();
答案 5 :(得分:-1)
我的理解是:你有一个像String sequence =“1234567891011121314”这样的序列字符串;
你想在这里找到输入String的第一次出现的索引(“910”)。
如果我的理解是正确的,我们在Java中有内置函数来执行此操作 - sequence.indexOf(input_string) - String str = "1234567891011121314";
String sub = "910";
System.out.println(str.indexOf(sub));