পাইথনে কোনও স্ট্রিং পুনরাবৃত্তি করে তবে আমি কীভাবে তা বলতে পারি?


352

আমি প্রদত্ত স্ট্রিং পুরো স্ট্রিংয়ের জন্য পুনরাবৃত্তি করে কিনা তা পরীক্ষা করার একটি উপায় অনুসন্ধান করছি।

উদাহরণ:

[
    '0045662100456621004566210045662100456621',             # '00456621'
    '0072992700729927007299270072992700729927',             # '00729927'
    '001443001443001443001443001443001443001443',           # '001443'
    '037037037037037037037037037037037037037037037',        # '037'
    '047619047619047619047619047619047619047619',           # '047619'
    '002457002457002457002457002457002457002457',           # '002457'
    '001221001221001221001221001221001221001221',           # '001221'
    '001230012300123001230012300123001230012300123',        # '00123'
    '0013947001394700139470013947001394700139470013947',    # '0013947'
    '001001001001001001001001001001001001001001001001001',  # '001'
    '001406469760900140646976090014064697609',              # '0014064697609'
]

স্ট্রিংগুলি যা নিজেদের পুনরাবৃত্তি করে এবং

[
    '004608294930875576036866359447',
    '00469483568075117370892018779342723',
    '004739336492890995260663507109',
    '001508295625942684766214177978883861236802413273',
    '007518796992481203',
    '0071942446043165467625899280575539568345323741',
    '0434782608695652173913',
    '0344827586206896551724137931',
    '002481389578163771712158808933',
    '002932551319648093841642228739',
    '0035587188612099644128113879',
    '003484320557491289198606271777',
    '00115074798619102416570771',
]

না এমনগুলির উদাহরণ।

আমার দেওয়া স্ট্রিংগুলির পুনরাবৃত্তি বিভাগগুলি দীর্ঘ দীর্ঘ হতে পারে এবং স্ট্রিংগুলি নিজেরাই 500 বা ততোধিক অক্ষর হতে পারে, সুতরাং প্রতিটি চরিত্রটি একটি প্যাটার্ন তৈরির চেষ্টা করছে তারপরে বাকী স্ট্রিংটির বনাম প্যাটার্নটি পরীক্ষা করা অত্যন্ত ধীর বলে মনে হচ্ছে। সম্ভাব্য কয়েকশো স্ট্রিং দ্বারা এটির গুণ করুন এবং আমি কোনও স্বজ্ঞাত সমাধান দেখতে পাচ্ছি না।

আমি কিছুটা রেইজেক্সে দেখেছি এবং যখন আপনি কী কী সন্ধান করছেন তা জানেন বা কমপক্ষে আপনি যে প্যাটার্নটি সন্ধান করছেন তা তাদের পক্ষে ভাল লাগবে। দুর্ভাগ্যক্রমে, আমি না জানি।

কোনও স্ট্রিং নিজেই পুনরাবৃত্তি করছে কিনা তা আমি কীভাবে বলতে পারি এবং যদি তা হয় তবে সংক্ষিপ্ততম পুনরাবৃত্তিটি পরবর্তীটি কী?


15
একটি প্যাটার্ন তৈরির চেষ্টা করে প্রতিটি চরিত্রের মধ্য দিয়ে লুপিং করা হচ্ছে তারপরে প্যাটার্নটি বনাম বাকী স্ট্রিংটি ভীষণ ধীর মনে হচ্ছে - তবে এটি কি?
টিম


2
@ অভিনাশরাজ এটি একটি স্ট্রিংয়ের অংশের সাথে কেবল মিলছে, সম্পূর্ণ জিনিস নয়।
জন

11
@ অভিনশরাজরাজ ওপি সম্ভাব্য সমস্ত সমাধান সম্পর্কে জিজ্ঞাসা করছে। আপনি যে প্রশ্নটির সাথে লিঙ্ক করেছেন কেবলমাত্র রেজেক্স সমাধানটি গ্রহণ করে । দ্রষ্টব্য যে রেজেক্স সমস্যা সমাধান করতে সক্ষম হতে পারে তবে প্রয়োজনের চেয়ে অনেক বেশি সময়। উদাহরণস্বরূপ একটি সর্বোত্তম সমাধান (যেমন লিনিয়ার সময়) পাঠ্যের প্রত্যয় গাছটি ব্যবহার করবে। আপনাকে কেবল দীর্ঘতম পুনরাবৃত্ত সাবস্ট্রিং সন্ধান করতে হবে এবং দৈর্ঘ্যের উপর কিছু পরীক্ষা করতে হবে।
বাকুরিউ

2
@ টাইগারহকটি 3 আসল ডেটাসেটটি অনেক বেশি বড় এবং অযথাযুক্ত, তবে প্রশ্নের উদাহরণগুলি এর অংশ, এবং আপনি যদি চান তবে এখানে আরও কিছু
জন

উত্তর:


570

এখানে একটি সংক্ষিপ্ত সমাধান যা নিয়মিত প্রকাশগুলি এড়িয়ে যায় এবং পাইথন লুপগুলিকে ধীর করে দেয়:

def principal_period(s):
    i = (s+s).find(s, 1, -1)
    return None if i == -1 else s[:i]

বেঞ্চমার্ক ফলাফলের জন্য ডেভিডিজম দ্বারা শুরু করা সম্প্রদায় উইকি উত্তর দেখুন । সংক্ষেপে,

ডেভিড জাং এর সমাধানটি পরিষ্কার বিজয়ী, বড় উদাহরণের জন্য কমপক্ষে 5x দ্বারা অন্য সকলকে ছাড়িয়ে যান।

(এই উত্তরটির কথাগুলি, আমার নয়))

এটি পর্যবেক্ষণের উপর ভিত্তি করে তৈরি করা হয় যে কোনও স্ট্রিং পর্যায়ক্রমিক হয় এবং কেবল যদি এটি নিজের কোনও অযৌক্তিক ঘূর্ণনের সমান হয়। নিরূপক যে আমরা তারপর প্রথম ঘটনার সূচি থেকে প্রধান সময়ের পুনরুদ্ধার করতে @AleksiTorhamo যশ sমধ্যে (s+s)[1:-1], এবং আমাকে ঐচ্ছিক এর পরিচায়ক জন্য startএবং endপাইথন এর অফ আর্গুমেন্ট string.find


19
আপনি এটি ব্যবহার করে .find()বা .index()পরিবর্তে, এর দ্বারা সংক্ষিপ্ততম পুনরাবৃত্তি পর্বগুলি সন্ধান করতে এটি প্রসারিত করতে পারেন in(s+s).find(s, 1, -1)
আলেকসি তোড়হামো

11
এছাড়াও, আমি মনে করি কমপক্ষে বড় স্ট্রিংয়ের (s+s).find(s, 1, -1)চেয়ে (খুব সামান্য) দ্রুততর হবে (s+s)[1:-1].find(s), যেহেতু টুকরো টুকরো করার অর্থ আপনাকে সম্পূর্ণ স্ট্রিংয়ের প্রায় একটি অনুলিপি তৈরি করতে হবে।
আলেকসি তোড়হামো

13
এটি আপনি যদি পর্যায়ক্রমিক ক্রিয়াকলাপ থেকে কোনও পাপ বা কোস ওয়েভ নেন এবং এটিকে ডানদিকে স্থানান্তর করেন It's যেহেতু এটি পুরোপুরি পর্যায়ক্রমিক, তরঙ্গগুলি শেষ পর্যন্ত পুরোপুরি মিলবে ... এই সমাধানের গণিতের সমান্তরালগুলি কেবল অসাধারণ। :) আমি আশা করি আমি আপনাকে + ∞ ​​উন্নতি দিতে পারতাম।
শশাঙ্ক

6
গাইডো এর সাম্প্রতিক আপডেট করার PEP 8 এখানে প্রাসঙ্গিক: "রিটার্ন স্টেটমেন্ট মধ্যে সামঞ্জস্যপূর্ণ হতে হয় একটি ফাংশন সমস্ত রিটার্ন স্টেটমেন্ট একটি অভিব্যক্তি আসতে উচিত, বা তাদের কেউ উচিত।। কোন রিটার্ন স্টেটমেন্ট আয় যদি একটি অভিব্যক্তি, কোন রিটার্ন স্টেটমেন্ট কোনো মূল্যই যেখানে প্রত্যাবর্তিত ব্যক্তিকে এটিকে স্পষ্টরূপে রিটার্ন নয় হিসাবে উল্লেখ করা উচিত এবং ফাংশনটির শেষে (যদি পৌঁছতে পারে) একটি সুস্পষ্ট রিটার্ন বিবৃতি উপস্থিত থাকতে হবে । "
জিরো পাইরেয়াস

8
@WayneConrad একটি স্ট্রিং নিন, বলুন, "abcd"ডানদিকে অক্ষরটি পপ করুন এবং এটি পেতে বাম দিকে আটকে দিন "dabc"। এই পদ্ধতিটিকে 1 টি অক্ষর দ্বারা ডানদিকে স্ট্রিং ঘোরানো বলে । অক্ষর nদ্বারা ডানদিকে একটি স্ট্রিং ঘোরানোর জন্য পুনরাবৃত্তি করুন n। এখন লক্ষ করুন যে আমাদের যদি kঅক্ষরের একটি স্ট্রিং থাকে তবে ডানদিকে ঘুরতে কোনও একাধিক kপাতা দিয়ে স্ট্রিং অপরিবর্তিত থাকে। স্ট্রিংয়ের একটি অননুমোদিত ঘূর্ণন এমন একটি যার অক্ষর সংখ্যা স্ট্রিংয়ের দৈর্ঘ্যের একাধিক নয়।
ডেভিড জাং

181

নিয়মিত এক্সপ্রেশন ব্যবহার করে একটি সমাধান এখানে।

import re

REPEATER = re.compile(r"(.+?)\1+$")

def repeated(s):
    match = REPEATER.match(s)
    return match.group(1) if match else None

প্রশ্নের উদাহরণগুলিতে আইট্রেটিং:

examples = [
    '0045662100456621004566210045662100456621',
    '0072992700729927007299270072992700729927',
    '001443001443001443001443001443001443001443',
    '037037037037037037037037037037037037037037037',
    '047619047619047619047619047619047619047619',
    '002457002457002457002457002457002457002457',
    '001221001221001221001221001221001221001221',
    '001230012300123001230012300123001230012300123',
    '0013947001394700139470013947001394700139470013947',
    '001001001001001001001001001001001001001001001001001',
    '001406469760900140646976090014064697609',
    '004608294930875576036866359447',
    '00469483568075117370892018779342723',
    '004739336492890995260663507109',
    '001508295625942684766214177978883861236802413273',
    '007518796992481203',
    '0071942446043165467625899280575539568345323741',
    '0434782608695652173913',
    '0344827586206896551724137931',
    '002481389578163771712158808933',
    '002932551319648093841642228739',
    '0035587188612099644128113879',
    '003484320557491289198606271777',
    '00115074798619102416570771',
]

for e in examples:
    sub = repeated(e)
    if sub:
        print("%r: %r" % (e, sub))
    else:
        print("%r does not repeat." % e)

... এই আউটপুট উত্পাদন করে:

'0045662100456621004566210045662100456621': '00456621'
'0072992700729927007299270072992700729927': '00729927'
'001443001443001443001443001443001443001443': '001443'
'037037037037037037037037037037037037037037037': '037'
'047619047619047619047619047619047619047619': '047619'
'002457002457002457002457002457002457002457': '002457'
'001221001221001221001221001221001221001221': '001221'
'001230012300123001230012300123001230012300123': '00123'
'0013947001394700139470013947001394700139470013947': '0013947'
'001001001001001001001001001001001001001001001001001': '001'
'001406469760900140646976090014064697609': '0014064697609'
'004608294930875576036866359447' does not repeat.
'00469483568075117370892018779342723' does not repeat.
'004739336492890995260663507109' does not repeat.
'001508295625942684766214177978883861236802413273' does not repeat.
'007518796992481203' does not repeat.
'0071942446043165467625899280575539568345323741' does not repeat.
'0434782608695652173913' does not repeat.
'0344827586206896551724137931' does not repeat.
'002481389578163771712158808933' does not repeat.
'002932551319648093841642228739' does not repeat.
'0035587188612099644128113879' does not repeat.
'003484320557491289198606271777' does not repeat.
'00115074798619102416570771' does not repeat.

নিয়মিত প্রকাশটি (.+?)\1+$তিন ভাগে বিভক্ত:

  1. (.+?)কোনও চরিত্রের কমপক্ষে একটি (তবে যত কম সম্ভব) সমন্বিত একটি গ্রুপের মিল রয়েছে (কারণ +?এটি লোভী নয় )।

  2. \1+ প্রথম অংশে ম্যাচিং গ্রুপের কমপক্ষে একটি পুনরাবৃত্তি পরীক্ষা করে।

  3. $স্ট্রিংয়ের সমাপ্তির জন্য, বারবার সাবস্ট্রিংয়ের পরে কোনও অতিরিক্ত, অ-পুনরাবৃত্তিযোগ্য সামগ্রী নেই তা নিশ্চিত করার জন্য পরীক্ষা করে (এবং re.match()এটি নিশ্চিত করে যে পুনরাবৃত্ত সাবস্ট্রিংয়ের আগে কোনও পুনরাবৃত্তি পাঠ্য নেই )।

পাইথন ৩.৪ এবং তারপরে, আপনি তার পরিবর্তে $ব্যবহার করতে পারেন re.fullmatch()বা (যে কোনও পাইথনে কমপক্ষে ২.৩ হিসাবে পিছনে) অন্যভাবে যেতে পারেন re.search()এবং রেইগেক্সের সাথে ব্যবহার করতে পারেন ^(.+?)\1+$, এগুলি সমস্ত কিছুর চেয়ে ব্যক্তিগত স্বাদে আরও নিচে রয়েছে।


6
কেন এই সংক্ষিপ্ত দুটি লাইনার সর্বোচ্চ ভোটের উত্তর নয় তা আমার কোনও ধারণা নেই। অন্যান্য উত্তরগুলি খারাপ নয়, তবে এটি একটি আরও ভাল। (এটি ঘন ঘন অস্বীকৃত নিয়মিত অভিব্যক্তিটি ব্যবহার করতে পারে তবে অন্যান্য দীর্ঘ উত্তরগুলির তুলনায় আমি এটি আরও সহজ পরিদর্শন করতে পারি, যা নেস্টেড ব্লক, সম্ভাব্য টাইপস, একের পর এক ত্রুটি ইত্যাদিতে পূর্ণ) আহা ভাল, আরও খারাপ আরও ভাল আমি ধরে নিচ্ছি.
পল ড্রাগন

9
আমি এর দুটি প্রধান কারণ আছে বলে মনে করি: 1) কিছু প্রোগ্রামার গণিত পছন্দ করে যা তারা রেজিজেস পছন্দ করে, এবং 2) যেহেতু ইনপুট স্ট্রিংগুলির দৈর্ঘ্য এবং প্রকৃতির ভিন্নতা বিভিন্ন উত্তরকে পারফরম্যান্সের দিকে এগিয়ে নিয়ে যায়, সুপার-দীর্ঘ প্রান্তের কেস স্ট্রিংগুলি (যা প্রকৃত ডেটাতে প্রদর্শিত নাও হতে পারে) এই সমাধানটিকে সাবঅপটিমাল হিসাবে উপস্থিত করে।
টাইগারহকটি 3

কখনও কখনও আপনি নিয়মিত প্রকাশের প্রতি দুর্দান্ত কুসংস্কারের মুখোমুখি হন। আইভের 2 জন পরিচালক ছিলেন যারা নিয়মিত এক্সপ্রেশন ব্যবহার নিষিদ্ধ করেছিলেন কারণ তারা শুনেছেন যে নিয়মিত এক্সপ্রেশনটি কাজের জন্য ভুল সরঞ্জাম। অফকোর্স বাদে তারা আমাকে একটি
রেইগএক্সএক্স

1
@ পলড্রাপার: অনুমান করুন যে রেজেক্স পর্দার আড়ালে কী করছে? এটি স্ট্রিংকে বিশ্লেষণ করছে এবং একটি ধনাত্মক পুনর্বিবেচনার ম্যাচ না হওয়া পর্যন্ত প্রতিটি উপাদান সংরক্ষণ করে। ওপি খুব ধীর হিসাবে যা বলেছে একই রকম। সুতরাং এটি 2 লাইনার হওয়ার কারণে কোনও কার্যকারিতা নেই isn't
dhein

2
@Zaibis, আমি সাধারণত একমত চাই, কিন্তু এই উভয় সবচেয়ে কম ও দ্রুততম সমাধান (হয় stackoverflow.com/a/29482936/1212596)....Except ডেভিড এর, যার পরে আমি যে মন্তব্য করেন পোস্ট করা হয়েছে জন্য। আমি আসলে ডেভিডের পদ্ধতিকে আরও পছন্দ করি (চালাক!)।
পল ড্রাগন

90

আপনি পর্যবেক্ষণটি করতে পারেন যে স্ট্রিংটির পুনরাবৃত্তি হিসাবে বিবেচিত হওয়ার জন্য, এর পুনরাবৃত্ত ক্রমের দৈর্ঘ্যের দ্বারা দৈর্ঘ্যটি অবশ্যই বিভাজ্য হতে হবে। প্রদত্ত যে, এখানে একটি সমাধান যা থেকে দৈর্ঘ্য ভাজক উত্পন্ন হয় 1করতে n / 2সমেত, ভাজক দৈর্ঘ্য সঙ্গে সাবস্ট্রিং মধ্যে মূল পংক্তি ভাগ, এবং এর ফলে সেটের সমতা পরীক্ষা:

from math import sqrt, floor

def divquot(n):
    if n > 1:
        yield 1, n
    swapped = []
    for d in range(2, int(floor(sqrt(n))) + 1):
        q, r = divmod(n, d)
        if r == 0:
            yield d, q
            swapped.append((q, d))
    while swapped:
        yield swapped.pop()

def repeats(s):
    n = len(s)
    for d, q in divquot(n):
        sl = s[0:d]
        if sl * q == s:
            return sl
    return None

সম্পাদনা: পাইথন 3 এ /অপারেটরটি ডিফল্টরূপে ভাসমান বিভাগ করতে পরিবর্তিত হয়েছে। intপাইথন 2 থেকে বিভাগ পেতে , আপনি তার //পরিবর্তে অপারেটরটি ব্যবহার করতে পারেন । এটি আমার নজরে আনার জন্য @ টাইগারহকটি 3 কে আপনাকে ধন্যবাদ।

//উভয় পাইথন 2 এবং পাইথন 3 বিভাজন পূর্ণসংখ্যা অপারেটর সঞ্চালিত, তাই আমি উত্তর উভয় সংস্করণই সমর্থন করার জন্য আপডেট করেছি। যে অংশটি আমরা পরীক্ষা করে দেখছি যে সমস্ত সাবস্ট্রিংগুলি সমান কিনা তা এখন একটি সংক্ষিপ্ত-সার্কিট ক্রিয়াকলাপ allএবং জেনারেটর এক্সপ্রেশন ব্যবহার করে ।

আপডেট: মূল প্রশ্নের পরিবর্তনের প্রতিক্রিয়া হিসাবে, কোডটি এখন ক্ষুদ্রতম পুনরাবৃত্তি সাবস্ট্রিং উপস্থিত থাকলে এবং Noneযদি তা না থাকে তবে ফিরে আসতে আপডেট করা হয়েছে । @ গুডলিগেক জেনারেটরে divmodপুনরাবৃত্তির সংখ্যা হ্রাস করার জন্য ব্যবহার করার পরামর্শ দিয়েছেন এবং কোডটিও এটির divisorsসাথে মিলিয়ে আপডেট করা হয়েছে। এটি এখন নিজেই nএকচেটিয়া ক্রমের সমস্ত ধনাত্মক বিভাজক ফেরত nদেয়।

উচ্চ পারফরম্যান্সের জন্য আরও আপডেট: একাধিক পরীক্ষার পরে, আমি এই সিদ্ধান্তে পৌঁছেছি যে স্ট্রিং ইক্যুয়ালিটির জন্য কেবল টেস্টিংয়ের পাইথনের কোনও কাটা বা পুনরুদ্ধারের সমাধানের মধ্যে সেরা পারফরম্যান্স রয়েছে। সুতরাং, আমি @ টাইগারহোকটি 3 এর বইয়ের একটি পাতা বের করে আমার সমাধানটি আপডেট করেছি। এটি এখন আগের তুলনায় 6x এরও বেশি দ্রুত, টাইগারহকের সমাধানের চেয়ে লক্ষণীয়ভাবে দ্রুত কিন্তু ডেভিডের চেয়ে ধীর।


3
এই সমাধানটি আশ্চর্যজনক। উত্পাদন-ভোক্তা নিদর্শন অনুসরণ করতে আপনি বিভাজক পদ্ধতি পরিবর্তন করতে পারেন। যাতে এটি পাওয়া যায় তার ফলস্বরূপ। এটি যদি সর্বোচ্চ উত্তর না হয় তবে লজ্জার বিষয় হবে। অন্য সব কিছুই নিষ্ঠুর শক্তি।
জাস্টিনডানিয়েলসন

3
@ জাস্টিনডানিয়েলসন এটি জেনারেটর এক্সপ্রেশন থেকে তৈরি একটি জেনারেটর অবজেক্ট ফিরিয়ে দেয়, যা অন্তর্ভুক্ত প্রযোজক :) এটি বিভাজনকারীদের অলস-মূল্যায়ন করবে।
শশাঙ্ক

1
ওহ। আমি এটা জানতাম না। ঠিক আছে, আরও ভাল তারপর। : ডিআই বুঝতে পারে আপনি স্কয়ারটি এড়াতে কেন, কিন্তু আপনি বিভাজক ব্যাপ্তির জন্য উপরের সীমা হিসাবে n / 2 ব্যবহার করতে পারেন।
জাস্টিনডানিয়েলসন

1
@ জাস্টিনডানিয়েলসন এই পরামর্শের জন্য ধন্যবাদ, উপরের সীমাটি এখন (n/2)অন্তর্ভুক্ত।
শশাঙ্ক

1
করা উচিত n / 2মধ্যে divisors()হতে n // 2?
টাইগারহকটি 3

87

এই প্রশ্নের বিভিন্ন উত্তরের জন্য কিছু মানদণ্ড এখানে দেওয়া হল। স্ট্রিংটি পরীক্ষা করা হচ্ছে তার উপর নির্ভর করে বন্যভাবে বিভিন্ন পারফরম্যান্স সহ কিছু বিস্ময়কর ফলাফল ছিল results

পাইথন 3 এর সাথে কাজ করার জন্য কিছু ফাংশন সংশোধন করা হয়েছিল (প্রধানত পূর্ণসংখ্যা বিভাগ নিশ্চিত করার /সাথে প্রতিস্থাপন করে //)। যদি আপনি কিছু ভুল দেখেন, আপনার ফাংশনটি যুক্ত করতে চান বা পাইথন চ্যাটরুমে @ জিরোপিরয়েসকে পিং করে অন্য একটি পরীক্ষা স্ট্রিং যুক্ত করতে চান ।

সংক্ষিপ্তসার: এখানে ওপি দ্বারা সরবরাহিত উদাহরণের বড় সংখ্যার ( এই মন্তব্যের মাধ্যমে ) সর্বোত্তম- এবং সবচেয়ে খারাপ-পারফরম্যান্স সমাধানের মধ্যে প্রায় 50x পার্থক্য রয়েছে । ডেভিড জাং এর সমাধানটি পরিষ্কার বিজয়ী, বড় উদাহরণের জন্য প্রায় 5x দ্বারা সমস্ত অন্যান্যকে ছাড়িয়ে যায়।

উত্তর দুটি মিলিয়ে অত্যন্ত বড় "কোনও মিল নেই" ক্ষেত্রে খুব ধীর। অন্যথায়, ফাংশনগুলি পরীক্ষার উপর নির্ভর করে সমান মেলে বা পরিষ্কার বিজয়ী বলে মনে হয়।

বিভিন্ন বিতরণ দেখানোর জন্য ম্যাটপ্ল্লোলিব এবং সমুদ্র সৈকত ব্যবহার করে নির্মিত প্লটগুলি সহ এখানে ফলাফল রয়েছে:


কর্পস 1 (সরবরাহিত উদাহরণ - ছোট সেট)

mean performance:
 0.0003  david_zhang
 0.0009  zero
 0.0013  antti
 0.0013  tigerhawk_2
 0.0015  carpetpython
 0.0029  tigerhawk_1
 0.0031  davidism
 0.0035  saksham
 0.0046  shashank
 0.0052  riad
 0.0056  piotr

median performance:
 0.0003  david_zhang
 0.0008  zero
 0.0013  antti
 0.0013  tigerhawk_2
 0.0014  carpetpython
 0.0027  tigerhawk_1
 0.0031  davidism
 0.0038  saksham
 0.0044  shashank
 0.0054  riad
 0.0058  piotr

কর্পাস 1 গ্রাফ


কর্পস 2 (সরবরাহিত উদাহরণ - বড় সেট)

mean performance:
 0.0006  david_zhang
 0.0036  tigerhawk_2
 0.0036  antti
 0.0037  zero
 0.0039  carpetpython
 0.0052  shashank
 0.0056  piotr
 0.0066  davidism
 0.0120  tigerhawk_1
 0.0177  riad
 0.0283  saksham

median performance:
 0.0004  david_zhang
 0.0018  zero
 0.0022  tigerhawk_2
 0.0022  antti
 0.0024  carpetpython
 0.0043  davidism
 0.0049  shashank
 0.0055  piotr
 0.0061  tigerhawk_1
 0.0077  riad
 0.0109  saksham

কর্পাস 1 গ্রাফ


কর্পস 3 (প্রান্তের কেস)

mean performance:
 0.0123  shashank
 0.0375  david_zhang
 0.0376  piotr
 0.0394  carpetpython
 0.0479  antti
 0.0488  tigerhawk_2
 0.2269  tigerhawk_1
 0.2336  davidism
 0.7239  saksham
 3.6265  zero
 6.0111  riad

median performance:
 0.0107  tigerhawk_2
 0.0108  antti
 0.0109  carpetpython
 0.0135  david_zhang
 0.0137  tigerhawk_1
 0.0150  shashank
 0.0229  saksham
 0.0255  piotr
 0.0721  davidism
 0.1080  zero
 1.8539  riad

কর্পস 3 গ্রাফ


পরীক্ষা এবং কাঁচা ফলাফল এখানে পাওয়া যায়


37

নন-রেজেক্স সমাধান:

def repeat(string):
    for i in range(1, len(string)//2+1):
        if not len(string)%len(string[0:i]) and string[0:i]*(len(string)//len(string[0:i])) == string:
            return string[0:i]

দ্রুততর নন-রেজেক্স সমাধান, @ থ্যাটওয়ার্ডোকে ধন্যবাদ (মন্তব্য দেখুন):

def repeat(string):
    l = len(string)
    for i in range(1, len(string)//2+1):
        if l%i: continue
        s = string[0:i]
        if s*(l//i) == string:
            return s

উপরের সমাধানটি কয়েক শতাংশের তুলনায় মূলের তুলনায় খুব কমই ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে যায় sometimes এটি এখনও লম্বা স্ট্রিংগুলির জন্য ডেভিডিজমের চেয়ে দ্রুত নয় এবং শূন্যের রেজেক্স সমাধান সংক্ষিপ্ত স্ট্রিংয়ের চেয়ে সেরা। এটি প্রায় 1000-1500 অক্ষরের স্ট্রিং সহ দ্রুততম (গিথুবের উপর ডেভিডিজমের পরীক্ষা অনুযায়ী - তার উত্তর দেখুন) এ বেরিয়ে আসে। নির্বিশেষে, আমি পরীক্ষিত সমস্ত ক্ষেত্রে এটি নির্ভরযোগ্যভাবে দ্বিতীয়-দ্রুত (বা আরও ভাল)। ধন্যবাদ, থ্যাটওয়ার্ডো

টেস্ট:

print(repeat('009009009'))
print(repeat('254725472547'))
print(repeat('abcdeabcdeabcdeabcde'))
print(repeat('abcdefg'))
print(repeat('09099099909999'))
print(repeat('02589675192'))

ফলাফল:

009
2547
abcde
None
None
None

এটি কি একটি নিষ্ঠুর শক্তি সমাধান নয়?
জাস্টিনডানিয়েলসন

7
@ জাস্টিনডানিয়েলসন হ্যাঁ তবে এর সমাধানও কম নয়।
সিংকিপয়েন্ট

3
আমি সংক্ষিপ্ত স্ট্রিংগুলির জন্য প্রায় 1e-5 থেকে 3e-5 সেকেন্ড, সফল দীর্ঘ (1000-অক্ষর) স্ট্রিংয়ের জন্য 3e-5 থেকে 4e-5 সেকেন্ড এবং ব্যর্থ দীর্ঘ দীর্ঘ স্ট্রিংয়ের জন্য কিছুটা এক মিলিসেকেন্ডের নীচে (সবচেয়ে খারাপ পরিস্থিতি) দেখছি । সুতরাং এক হাজার 1000-চরিত্রের স্ট্রিংগুলিতে প্রায় এক সেকেন্ড সময় লাগবে। গণিতের উত্তরের তুলনায়, এটি 10 ​​বার দ্রুত ম্যাচগুলি আবিষ্কার করে তবে ব্যর্থ হতে 3 বার বেশি সময় নেয়।
টাইগারহকটি 3

repeat('aa')ফেরতNone
টম কর্নাইবাইজ

2
len(string[0:i])সর্বদা সমান i(কমপক্ষে এই ক্ষেত্রে)। এগুলি প্রতিস্থাপন করা, এবং সংরক্ষণ len(string)এবং string[0:i]ভেরিয়েবলগুলিতে জিনিসগুলি গতি বাড়িয়ে দিতে পারে। এছাড়াও আইএমও এটি দুর্দান্ত সমাধান, দুর্দান্ত;)
ThatWeirdo

24

প্রথমে স্ট্রিংটি "2 অংশ" নকল হিসাবে যতক্ষণ না অর্ধেক করুন। যদি পুনরাবৃত্তি করার জন্য এমনকি সংখ্যক সংখ্যা থাকে তবে এটি অনুসন্ধানের স্থান হ্রাস করে। তারপরে, ক্ষুদ্রতম পুনরাবৃত্তি স্ট্রিং সন্ধানের জন্য এগিয়ে কাজ করে, কেবলমাত্র খালি মানগুলিতে ক্রমবর্ধমান বৃহত্তর সাব-স্ট্রিংয়ের ফলাফল দ্বারা পূর্ণ স্ট্রিংকে বিভক্ত করা হয়েছে কিনা তা পরীক্ষা করুন। কেবলমাত্র সাব-স্ট্রিংগুলির length // 2পরীক্ষা করা দরকার কারণ যে কোনও কিছুর পুনরাবৃত্তি হবে না।

def shortest_repeat(orig_value):
    if not orig_value:
        return None

    value = orig_value

    while True:
        len_half = len(value) // 2
        first_half = value[:len_half]

        if first_half != value[len_half:]:
            break

        value = first_half

    len_value = len(value)
    split = value.split

    for i in (i for i in range(1, len_value // 2) if len_value % i == 0):
        if not any(split(value[:i])):
            return value[:i]

    return value if value != orig_value else None

এটি সংক্ষিপ্ততম ম্যাচটি বা কোনও মিল না থাকলে কোনও ফেরত দেয় returns


16

O(n)উপসর্গ ফাংশন সহ সমস্যাটি সবচেয়ে খারাপ ক্ষেত্রেও সমাধান হতে পারে ।

দ্রষ্টব্য, এটি সাধারণ ক্ষেত্রে (ইউপিডি: এবং অনেক ধীর গতিতে) ধীরে ধীরে অন্যান্য বিভাজনগুলির উপর নির্ভর করে যা অন্যান্য বিভাজনগুলির উপর নির্ভর করে n, তবে সাধারণত শীঘ্রই ব্যর্থ হয়, আমি মনে করি তাদের জন্য একটি খারাপ কেস হবে aaa....aab, যেখানে রয়েছে n - 1 = 2 * 3 * 5 * 7 ... *p_n - 1 as

সবার আগে আপনাকে প্রিফিক্স ফাংশন গণনা করতে হবে

def prefix_function(s):
    n = len(s)
    pi = [0] * n
    for i in xrange(1, n):
        j = pi[i - 1]
        while(j > 0 and s[i] != s[j]):
            j = pi[j - 1]
        if (s[i] == s[j]):
            j += 1
        pi[i] = j;
    return pi

তাহলে হয় উত্তর নেই বা সংক্ষিপ্ততম সময়কাল

k = len(s) - prefix_function(s[-1])

এবং আপনাকে ঠিক আছে কিনা তা পরীক্ষা করে দেখতে হবে k != n and n % k == 0 (যদি k != n and n % k == 0উত্তর হয় তবে s[:k]অন্যথায় কোনও উত্তর নেই

আপনি এখানে প্রমাণটি পরীক্ষা করতে পারেন (রাশিয়ান ভাষায়, তবে অনলাইন অনুবাদক সম্ভবত কৌশলটি করবেন)

def riad(s):
    n = len(s)
    pi = [0] * n
    for i in xrange(1, n):
        j = pi[i - 1]
        while(j > 0 and s[i] != s[j]):
            j = pi[j - 1]
        if (s[i] == s[j]):
            j += 1
        pi[i] = j;
    k = n - pi[-1]
    return s[:k] if (n != k and n % k == 0) else None

আপনার prefix_function()বৈধ পাইথন নয়: আপনার whileএবং ifবিবৃতিতে এবং এর &&পরিবর্তে আপনার কাছে কলোন রয়েছে and। সেগুলি ঠিক করার পরে, UnboundLocalError: local variable 'i' referenced before assignmentলাইনের কারণে এটি ব্যর্থ হয় for i in range(i, n):
জিরো পাইরেয়াস

ধন্যবাদ :-) আপনি যদি এমন কোনও ফাংশন একসাথে prefix_function()রাখতে পারেন যা অন্য উত্তরের সাথে একইরকম ফলাফল ফেরত দিতে ব্যবহার করে - তবে হয় সংক্ষিপ্ততম স্ট্রিং বা None- আমি একে সংশোধন করা মানদণ্ডে অন্তর্ভুক্ত করব together
জিরো পাইরেয়াস

@ জিরোপিরেস, এটি আসলে ভাল কাজ করে, আমি এটিকে কেবল একটি ভুল উপায়ে
বলেছি

16

এই সংস্করণটি কেবলমাত্র সেই প্রার্থীদের ক্রম দৈর্ঘ্যের চেষ্টা করে যা স্ট্রিং দৈর্ঘ্যের কারণ; এবং *প্রার্থী ক্রম থেকে পূর্ণ দৈর্ঘ্যের স্ট্রিং তৈরি করতে অপারেটরটি ব্যবহার করে :

def get_shortest_repeat(string):
    length = len(string)
    for i in range(1, length // 2 + 1):
        if length % i:  # skip non-factors early
            continue

        candidate = string[:i]
        if string == candidate * (length // i):
            return candidate

    return None

ঠাহর যে জন্য TigerhawkT3 ধন্যবাদ length // 2ছাড়া + 1মেলে ব্যর্থ হবে ababকেস।


এই সমাধানটি আমার অনুকূলিতের সাথে কার্যত অভিন্ন ually আমি দেখতে পাচ্ছি যে আপনার যেমন rangeসীমাবদ্ধতা রয়েছে ঠিক তেমনই length//2- আপনি length//2+1যদি ডাবল স্ট্রিংগুলি ধরতে চান তবে আপনাকে এটি পরিবর্তন করতে হবে (উদাঃ 'aabaab')।
টাইগারহকটি 3

এবং এখন তারা অভিন্ন! / o / ভবিষ্যতে অপ্টিমাইজেশনের দিকে আমার আরও মনোযোগ দেওয়া দরকার, তবে আমি নিজেই আনন্দিত যে অ্যালগোরিদম নিজেই সুস্বাদু ছিল।
টাইগারহকটি 3

15

রেজিক্স ছাড়াই এখানে একটি সরল ফরোয়ার্ড সমাধান।

sজিরোথ সূচক থেকে শুরু করে সাবস্ট্রিংয়ের জন্য , দৈর্ঘ্য 1 এর মাধ্যমে len(s), পরীক্ষা করে দেখুন যে সেই স্ট্রিংগুলি substrপুনরাবৃত্তি প্যাটার্ন। এই চেকটি substrনিজের সাথে ratioবারবার সংলগ্ন করে সম্পাদন করা যেতে পারে , যেমন স্ট্রিংয়ের দৈর্ঘ্য দৈর্ঘ্যের সমান হয় s। অত: পর ratio=len(s)/len(substr)

প্রথম যখন এই ধরনের সাবস্ট্রিং পাওয়া যায় তখন ফিরে আসুন। এটি উপস্থিত থাকলে ছোটতম সাবস্ট্রিং সরবরাহ করবে।

def check_repeat(s):
    for i in range(1, len(s)):
        substr = s[:i]
        ratio = len(s)/len(substr)
        if substr * ratio == s:
            print 'Repeating on "%s"' % substr
            return
    print 'Non repeating'

>>> check_repeat('254725472547')
Repeating on "2547"
>>> check_repeat('abcdeabcdeabcdeabcde')
Repeating on "abcde"

এখন যেহেতু আমি এটিকে মনোযোগ দিয়ে দেখছি, এটি আমার মূল পোস্ট করা (কোনও সম্পাদনার আগে) সমাধানের সাথে প্রায় একই রকম বলে মনে হচ্ছে, কেবলমাত্র পার্থক্য দৈর্ঘ্য এবং স্তরগুলি সংরক্ষণ করে। আমার ধারণা আমার খুব ভাল অ্যালগরিদম ছিল। : পি
টাইগারহকটি 3

@ টাইগারহকটি 3 হ্যাঁ! :)
দক্ষম ভার্মা

9

আমি এই সমস্যার আটটিরও বেশি সমাধান দিয়ে শুরু করেছি। কিছুগুলি রেজেক্সের ভিত্তি ছিল (ম্যাচ, ফান্ডাল, স্প্লিট), কিছু স্ট্রিং স্লাইসিং এবং টেস্টিং এবং কিছু স্ট্রিং পদ্ধতি সহ (সন্ধান, গণনা, বিভাজন)। প্রত্যেকের কোডের স্বচ্ছতা, কোডের আকার, গতি এবং মেমরির ব্যবহারের সুবিধাগুলি ছিল। আমি আমার উত্তর এখানে পোস্ট করতে যাচ্ছিলাম যখন দেখলাম মৃত্যুদন্ড কার্যকর করার গতিটিকে গুরুত্বপূর্ণ হিসাবে চিহ্নিত করা হয়েছে, তাই আমি এখানে পৌঁছানোর জন্য আরও পরীক্ষা ও উন্নতি করেছি:

def repeating(s):
    size = len(s)
    incr = size % 2 + 1
    for n in xrange(1, size//2+1, incr):
        if size % n == 0:
            if s[:n] * (size//n) == s:
                return s[:n]

এই উত্তরটি এখানে কয়েকটি অন্যান্য উত্তরের মতো বলে মনে হচ্ছে তবে এর কয়েকটি গতি অপ্টিমেশন রয়েছে যা অন্যরা ব্যবহার করেন নি:

  • xrange এই অ্যাপ্লিকেশনটিতে কিছুটা দ্রুত
  • যদি কোনও ইনপুট স্ট্রিং একটি বিজোড় দৈর্ঘ্য হয় তবে কোনও দৈর্ঘ্যের সাবস্ট্রিংগুলি যাচাই করবেন না,
  • s[:n]সরাসরি ব্যবহার করে আমরা প্রতিটি লুপে একটি পরিবর্তনশীল তৈরি এড়াতে পারি।

আমি সাধারণ হার্ডওয়্যার সহ স্ট্যান্ডার্ড পরীক্ষায় এটি কীভাবে সম্পাদন করে তা দেখতে আগ্রহী হব। আমি বিশ্বাস করি এটি বেশিরভাগ পরীক্ষায় ডেভিড জাংয়ের দুর্দান্ত অ্যালগরিদম থেকে খুব কম হবে তবে অন্যথায় এটি বেশ দ্রুত হওয়া উচিত।

আমি এই সমস্যাটি খুব পাল্টা স্বজ্ঞাত বলে মনে করেছি। সমাধানগুলি আমি দ্রুত বলে মনে করব তা ধীর ছিল। যে সমাধানগুলি ধীর দেখছিল তা দ্রুত ছিল! দেখে মনে হচ্ছে যে পাইথনের স্ট্রিং ক্রমটি বহুগুণ অপারেটর এবং স্ট্রিং তুলনার সাথে অত্যন্ত অনুকূলিত হয়েছে।


খারাপ না সব :-) এ পাইথন 3.4 তে বেঞ্চমার্ক রান (আংশিক কারণ ওপি একটি সংস্করণ নির্দিষ্ট করে না এবং যে এর সবাই কি উচিত ব্যবহার করে, এবং একারণে যে এটি নতুন ব্যবহার হতে statisticsমডিউল), তাই আমি আপনার পরিবর্তন করতে হয়েছিল /করার গুলি //গুলি এবং প্রতিস্থাপন xrange()সঙ্গে range()(যা 2.x আচরণ করবে মত এর xrange()3.x মধ্যে)।
জিরো পাইরেয়াস

এখানে মাপদণ্ডের সংশোধনগুলি রয়েছে , সুতরাং আপনি আমার পরিবর্তনগুলি পর্যালোচনা করতে পারেন।
জিরো পাইরেয়াস

ধন্যবাদ জিরো। এটা দ্রুত ছিল. ফলাফলগুলি আমার ভবিষ্যদ্বাণীগুলিতে কিছুটা কম ছিল। আমি সন্দেহ করি যে পাইথন ২.7-তে গতির জন্য আমি যে কৌশলগুলি ব্যবহার করেছি তা পাইথন ৩.৪-তে খুব কার্যকর নয়। ওহ, ভাল - একটি মজাদার এবং শিক্ষামূলক অনুশীলন।
লজিক নাইট

//3.x এ পূর্ণসংখ্যা বিভাগ (ঠিক যেমন 2.x এর আচরণের মত /) হয়, যখন 3.x এর /ফ্লোট বিভাগ (যা আমি নিশ্চিত যে এটি ব্যবহারের চেষ্টা করে আপনার সমাধানটি ভেঙে না দিলেও অনেক ধীর হয়ে যাবে) একটি সূচক হিসাবে একটি ভাসা)। উল্লিখিত হিসাবে, 3.x এর range()2.x এর একই জিনিস xrange(); ২.x এর কোনও সমমানের range()উপস্থিতি 3.x. তে নেই সুতরাং আমি মনে করি না যে এটি বেঞ্চমার্ক এবং আপনার যে কোনও সময় নির্ধারিত সময়ের মধ্যে কোনও বৈষম্যের কারণ। এটি সম্ভবত কেবলমাত্র 3.x 2x এর তুলনায় ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে or
জিরো পাইরেয়াস

যখন আমি কিছু সময় পেতে, আমি পাইথন 2 এবং পাইথন 3. মধ্যে রান-টাইম পার্থক্য এ ঘনিষ্ঠ কটাক্ষপাত আছে হইবে
লজিক নাইট

2

এই ফাংশনটি খুব দ্রুত সঞ্চালিত হয় (পরীক্ষিত এবং এটি 100k এর বেশি অক্ষরের স্ট্রিংগুলিতে দ্রুত সমাধানের চেয়ে 3 গুণ বেশি দ্রুত এবং পার্থক্যটি পুনরাবৃত্ত হওয়ার ধরণটি আরও দীর্ঘ হয়)। এটি উত্তর পেতে প্রয়োজনীয় তুলনা সংখ্যা হ্রাস করার চেষ্টা করে:

def repeats(string):
    n = len(string)
    tried = set([])
    best = None
    nums = [i for i in  xrange(2, int(n**0.5) + 1) if n % i == 0]
    nums = [n/i for i in nums if n/i!=i] + list(reversed(nums)) + [1]
    for s in nums:
        if all(t%s for t in tried):
            print 'Trying repeating string of length:', s
            if string[:s]*(n/s)==string:
                best = s
            else:
                tried.add(s)
    if best:
        return string[:best]

নোট করুন যে উদাহরণস্বরূপ 8 দৈর্ঘ্যের স্ট্রিংয়ের জন্য এটি 4 মাপের মাত্রার টুকরা পরীক্ষা করে এবং এটি আরও পরীক্ষা করতে হবে না কারণ 1 বা 2 দৈর্ঘ্যের প্যাটার্নের ফলে দৈর্ঘ্য 4 এর পুনরাবৃত্তি প্যাটার্ন হবে:

>>> repeats('12345678')
Trying repeating string of length: 4
None

# for this one we need only 2 checks 
>>> repeats('1234567812345678')
Trying repeating string of length: 8
Trying repeating string of length: 4
'12345678'

আপনাকে ধন্যবাদ :) আমি যদিও এটি এতটা অপ্টিমাইজ করি নি। আমি কেবল ভিন্ন দৃষ্টিভঙ্গি উপস্থাপন করতে চেয়েছিলাম কারণ অন্যান্য উত্তরগুলি প্যাটার্নটি সন্ধান করতে ফোকাস করছে এবং আমার পদ্ধতির প্রমাণ নেই যে কোনও প্যাটার্ন নেই :) তাই এলোমেলো স্ট্রিংগুলির জন্য আমার অ্যালগরিদমটি আরও দ্রুত চালানো উচিত।
পাইটর ডাবকভস্কি

0

ডেভিড ঝাং এর উত্তরে যদি আমাদের কাছে কোনও ধরণের বিজ্ঞপ্তি বাফার থাকে তবে এটি কাজ করবে না: principal_period('6210045662100456621004566210045662100456621')শুরু হওয়ার কারণে 621, যেখানে আমি এটি থুতু পছন্দ করতাম:00456621

তার সমাধানটি প্রসারিত করে আমরা নিম্নলিখিতটি ব্যবহার করতে পারি:

def principal_period(s):
    for j in range(int(len(s)/2)):
        idx = (s[j:]+s[j:]).find(s[j:], 1, -1)
        if idx != -1:
            # Make sure that the first substring is part of pattern
            if s[:j] == s[j:][:idx][-j:]:
                break

    return None if idx == -1 else s[j:][:idx]

principal_period('6210045662100456621004566210045662100456621')
>>> '00456621'

-1

পাইথনের কোডটি এখানে ব্যবহারকারী দ্বারা প্রদত্ত প্রধান স্ট্রিংয়ে সাব স্ট্রিংটির পুনরাবৃত্তি পরীক্ষা করে

print "Enter a string...."
#mainstring = String given by user
mainstring=raw_input(">")
if(mainstring==''):
    print "Invalid string"
    exit()
#charlist = Character list of mainstring
charlist=list(mainstring)
strarr=''
print "Length of your string :",len(mainstring)
for i in range(0,len(mainstring)):
    strarr=strarr+charlist[i]
    splitlist=mainstring.split(strarr)
    count = 0
    for j in splitlist:
        if j =='':
            count+=1
    if count == len(splitlist):
        break
if count == len(splitlist):
    if count == 2:
        print "No repeating Sub-String found in string %r"%(mainstring)

    else:
        print "Sub-String %r repeats in string %r"%(strarr,mainstring)
else :
    print "No repeating Sub-String found in string %r"%(mainstring)

ইনপুট :

0045662100456621004566210045662100456621

আউটপুট :

আপনার স্ট্রিংয়ের দৈর্ঘ্য: 40

সাব-স্ট্রিং '00456621' স্ট্রিংটিতে পুনরাবৃত্তি হয়েছে "0045662100456621004566210045662100456621 '

ইনপুট :

004608294930875576036866359447

আউটপুট :

আপনার স্ট্রিং দৈর্ঘ্য: 30

'004608294930875576036866359447' স্ট্রিংটিতে কোনও পুনরাবৃত্তি উপ-স্ট্রিং পাওয়া যায় নি

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.