Arrays 如何在给定数组中查找重复的字符序列?

Arrays 如何在给定数组中查找重复的字符序列?,arrays,algorithm,language-agnostic,Arrays,Algorithm,Language Agnostic,我的问题是找到给定数组中的重复字符序列。简单地说,识别字符出现的模式 ——————。 1:| J | A | M | E | S | O | N | J | A | M | E | S | O | N| —————————————————————————————————————————— ——————————。 2:| R | O | N | R | O | N | R | O | N | R | O | N| ——————————————————————————————————————————

我的问题是找到给定数组中的重复字符序列。简单地说,识别字符出现的模式

——————。
1:| J | A | M | E | S | O | N | J | A | M | E | S | O | N|
——————————————————————————————————————————

——————————。
2:| R | O | N | R | O | N | R | O | N | R | O | N|
————————————————————————————————————————————

————。
3:| S | H | A | M | I | L | S | H | A | M | I | L|
“——”——“——”——“——”——“——”——“——”——“——”——”

——————————。
4:| C | A | R | P | E | N | T | E | R | C | A | R | P | E | N | T | E | R|
————————————————————————————————————


例子 根据之前的数据,结果应为:

  • “詹姆逊”
  • “RON”
  • “SHAMIL”
  • “木匠”

  • 问题:
    • 如何有效地处理这个问题

      • 举个例子,我的第一个方法是

      • 获取数组的第一个字符(对于上一个示例,它将是
        C
      • 获取该字符在数组中下一次出现的索引(例如9)
      • 如果找到,则在字符的两个外观之间搜索子字符串的下一个外观(在本例中为
        CARPENTER
      • 如果找到了,就完成了(结果就是这个子字符串)
      • 当然,这只适用于可能数组的一个非常有限的子集,其中同一个单词从一开始就重复了一次又一次,中间没有散乱的字符,并且它的第一个字符在单词中不重复。但你们所有的例子都属于这一类——我更喜欢可能有效的最简单的解决方案:——)

        如果重复的单词多次包含第一个字符(例如,
        CACTUS
        ),则该算法可以扩展以查找该字符的后续出现,而不仅仅是第一个字符(以便它查找整个重复单词,而不仅仅是其子串)

        请注意,对于第二个示例,此扩展算法将给出不同的结果,即
        RONRON
        ,而不是
        RON

        伪代码

        len = str.length
        for (i in 1..len) {
           if (len%i==0) {
              if (str==str.substr(0,i).repeat(len/i)) {
                 return str.substr(0,i)
              }
           }
        }
        

        注意:为了简洁起见,我发明了一个字符串的“repeat”方法,它实际上不是Java字符串的一部分;在Python中,重复(2)=“abcabc”

        可以利用正则表达式,因此:

        def recurrence(text):
            import re
            for i in range(1, len(text)/2 + 1):
                m = re.match(r'^(.{%d})\1+$'%i, text)
                if m: return m.group(1)
        
        recurrence('abcabc') # Returns 'abc'
        
        我不确定这将如何转换为Java或C。(我想这是我喜欢Python的原因之一。:-

        使用C++:

        //Splits the string into the fragments of given size
        //Returns the set of of splitted strings avaialble
        set<string> split(string s, int frag)
        {
            set<string> uni;
            int len = s.length();
            for(int i = 0; i < len; i+= frag)
            {
                uni.insert(s.substr(i, frag));
            }
        
            return uni;
        }
        
        int main()
        {
        
            string out;
            string s = "carpentercarpenter";
            int len = s.length();
        
              //Optimistic approach..hope there are only 2 repeated strings
              //If that fails, then try to break the strings with lesser number of
              //characters
            for(int i = len/2; i>1;--i)
            {
                set<string> uni = split(s,i);
                if(uni.size() == 1)
                {
                    out = *uni.begin();
                    break;
                }
            }
        
            cout<<out;
            return 0;
        
        }
        
        //将字符串拆分为给定大小的片段
        //返回可用的拆分字符串集
        设置拆分(字符串s,整数帧)
        {
        设置uni;
        int len=s.length();
        对于(int i=0;i1;--i)
        {
        设置uni=拆分(s,i);
        如果(单位大小()==1)
        {
        out=*uni.begin();
        打破
        }
        }
        
        cout首先编写一个方法,在容器字符串中查找重复的子字符串
        sub
        ,如下所示

        boolean findSubRepeating(String sub, String container);
        

        现在继续在容器中增加子字符串来调用此方法,首先尝试1个字符的子字符串,然后是2个字符,以此类推到
        容器。length/2

        我想到的第一个想法是尝试所有长度除以长度的重复序列=N。此类长度的最大值为N/2,因此这将导致O(N^2)算法

        但我相信它可以改进…

        开玩笑的O(NlogN)解决方案


        对字符串执行FFT(将字符视为数值)。结果图中的每个峰值对应于子字符串周期。

        下面是一个具体的工作示例:

        /* find greatest repeated substring */
        char *fgrs(const char *s,size_t *l)
        {
          char *r=0,*a=s;
          *l=0;
          while( *a )
          {
            char *e=strrchr(a+1,*a);
            if( !e )
              break;
            do {
              size_t t=1;
              for(;&a[t]!=e && a[t]==e[t];++t);
              if( t>*l )
                *l=t,r=a;
              while( --e!=a && *e!=*a );
            } while( e!=a && *e==*a );
            ++a;
          }
          return r;
        }
        
          size_t t;
          const char *p;
          p=fgrs("BARBARABARBARABARBARA",&t);
          while( t-- ) putchar(*p++);
          p=fgrs("0123456789",&t);
          while( t-- ) putchar(*p++);
          p=fgrs("1111",&t);
          while( t-- ) putchar(*p++);
          p=fgrs("11111",&t);
          while( t-- ) putchar(*p++);
        

        我会将数组转换为字符串对象并使用regex,但不确定如何定义“高效”。为了便于/快速实现,您可以在Java中执行此操作:

            private static String findSequence(String text) {
                Pattern pattern = Pattern.compile("(.+?)\\1+");
                Matcher matcher = pattern.matcher(text);
                return matcher.matches() ? matcher.group(1) : null;
            }
        

        它试图找到最短的字符串(
        +?
        ),该字符串必须至少重复一次(
        \1+
        )才能匹配整个输入文本。

        将所有字符放入数组e.x.a[]

        i=0; j=0;
        for( 0 < i < count ) 
        {
        if (a[i] == a[i+j+1])
            {++i;}
        else
            {++j;i=0;}
        }
        
        i=0;j=0;
        对于(0
        然后(i/j)的比率=数组中的重复计数。
        您必须注意
        i
        j
        的限制,但这是一个简单的解决方案。

        这是一个更一般的问题解决方案,它将在一个序列(任何序列)中找到重复的子序列,其中子序列不必从开头开始,也不必立即彼此跟随

        给定一个序列b[0..n],包含所讨论的数据,阈值t是要查找的最小子序列长度

        l_max = 0, i_max = 0, j_max = 0;
        for (i=0; i<n-(t*2);i++) {
          for (j=i+t;j<n-t; j++) {
            l=0;
            while (i+l<j && j+l<n && b[i+l] == b[j+l])
              l++;
            if (l>t) {
              print "Sequence of length " + l + " found at " + i + " and " + j);
              if (l>l_max) {
                l_max = l;
                i_max = i;
                j_max = j;
              }
            }
          }
        }
        if (l_max>t) {
          print "longest common subsequence found at " + i_max + " and " + j_max + " (" + l_max + " long)";
        }
        
        l_max=0,i_max=0,j_max=0;
        
        对于(i=0;i我自己刚刚解决了这个问题,并为此编写了一些代码(用C#编写),其中有很多注释。希望这对某人有所帮助:

        //检查字符串是否包含重复序列。
        公共静态bool包含重复序列(string str)
        {
        if(string.IsNullOrEmpty(str))返回false;
        
        对于(inti=0;i这是我使用队列提出的解决方案,它通过了codeforces中类似问题的所有测试用例。问题号是745A

        #include<bits/stdc++.h>
        using namespace std;
        typedef long long ll;
        
        int main()
        {
            ios_base::sync_with_stdio(false);
            cin.tie(NULL);
        
            string s, s1, s2; cin >> s; queue<char> qu; qu.push(s[0]); bool flag = true; int ind = -1;
            s1 = s.substr(0, s.size() / 2);
            s2 = s.substr(s.size() / 2);
            if(s1 == s2)
            {
                for(int i=0; i<s1.size(); i++)
                {
                    s += s1[i];
                }
            }
            //cout << s1 << " " << s2 << " " << s << "\n";
            for(int i=1; i<s.size(); i++)
            {
                if(qu.front() == s[i]) {qu.pop();}
                qu.push(s[i]);
            }
            int cycle = qu.size();
        
            /*queue<char> qu2 = qu; string str = "";
            while(!qu2.empty())
            {
                cout << qu2.front() << " ";
                str += qu2.front();
                qu2.pop();
            }*/
        
        
            while(!qu.empty())
            {
                if(s[++ind] != qu.front()) {flag = false; break;}
                qu.pop();
            }
            flag == true ? cout << cycle : cout << s.size();
            return 0;
        }
        
        #包括
        使用名称空间std;
        typedef长
        
            private static String findSequence(String text) {
                Pattern pattern = Pattern.compile("(.+?)\\1+");
                Matcher matcher = pattern.matcher(text);
                return matcher.matches() ? matcher.group(1) : null;
            }
        
        i=0; j=0;
        for( 0 < i < count ) 
        {
        if (a[i] == a[i+j+1])
            {++i;}
        else
            {++j;i=0;}
        }
        
        l_max = 0, i_max = 0, j_max = 0;
        for (i=0; i<n-(t*2);i++) {
          for (j=i+t;j<n-t; j++) {
            l=0;
            while (i+l<j && j+l<n && b[i+l] == b[j+l])
              l++;
            if (l>t) {
              print "Sequence of length " + l + " found at " + i + " and " + j);
              if (l>l_max) {
                l_max = l;
                i_max = i;
                j_max = j;
              }
            }
          }
        }
        if (l_max>t) {
          print "longest common subsequence found at " + i_max + " and " + j_max + " (" + l_max + " long)";
        }
        
        #include<bits/stdc++.h>
        using namespace std;
        typedef long long ll;
        
        int main()
        {
            ios_base::sync_with_stdio(false);
            cin.tie(NULL);
        
            string s, s1, s2; cin >> s; queue<char> qu; qu.push(s[0]); bool flag = true; int ind = -1;
            s1 = s.substr(0, s.size() / 2);
            s2 = s.substr(s.size() / 2);
            if(s1 == s2)
            {
                for(int i=0; i<s1.size(); i++)
                {
                    s += s1[i];
                }
            }
            //cout << s1 << " " << s2 << " " << s << "\n";
            for(int i=1; i<s.size(); i++)
            {
                if(qu.front() == s[i]) {qu.pop();}
                qu.push(s[i]);
            }
            int cycle = qu.size();
        
            /*queue<char> qu2 = qu; string str = "";
            while(!qu2.empty())
            {
                cout << qu2.front() << " ";
                str += qu2.front();
                qu2.pop();
            }*/
        
        
            while(!qu.empty())
            {
                if(s[++ind] != qu.front()) {flag = false; break;}
                qu.pop();
            }
            flag == true ? cout << cycle : cout << s.size();
            return 0;
        }