কোন স্ট্রিং অনুসন্ধান অ্যালগরিদম আসলে সবচেয়ে দ্রুত?


27

আমি কিছু সময়ের জন্য আটকে ছিলাম যার উপর দ্রুততম স্ট্রিং অনুসন্ধান অ্যালগরিদম, অনেকগুলি মতামত শুনেছি, তবে শেষ পর্যন্ত আমি নিশ্চিত নই।

আমি কিছু লোককে বলতে শুনেছি যে দ্রুততম অ্যালগরিদম হলেন বায়ার-মুর এবং কেউ কেউ বলেছেন যে নুথ-মরিস-প্র্যাট আসলে দ্রুত faster

আমি উভয়ের জটিলতার সন্ধান করেছি কিন্তু তারা বেশিরভাগই একই রকম O(n+m)। আমি দেখতে পেয়েছি যে সবচেয়ে খারাপ পরিস্থিতিতে বায়ার-মুরের O(nm)নথ-মরিস-প্র্যাটের তুলনায় একটি জটিলতা রয়েছে যা হে (এম + 2 * এন) রয়েছে। যেখানে n = পাঠ্যের দৈর্ঘ্য এবং প্যাটার্নের দৈর্ঘ্য = m।

আমি যতদূর জানি বায়ার-মুরের ক্ষেত্রে রৈখিক-সবচেয়ে খারাপ কেস-টাইম থাকে যদি আমি গ্যালিল বিধিটি ব্যবহার করি।

আমার প্রশ্ন, সর্বোপরি আসলে সবচেয়ে দ্রুততম স্ট্রিং অনুসন্ধান অ্যালগরিদম (এই প্রশ্নটিতে কেবল বায়ার-মুর এবং নথ-মরিস-প্র্যাট নয়, সমস্ত সম্ভাব্য স্টিং অ্যালগরিদম অন্তর্ভুক্ত রয়েছে) Over

সম্পাদনা: এই উত্তরের কারণে

আমি ঠিক যা খুঁজছি তা হ'ল:

একটি টেক্সট দেওয়া Tএবং একটি প্যাটার্ন Pআমি সব চেহারাগুলো খুঁজে বের করতে হবে Pযে T

এছাড়াও পি এবং টি এর দৈর্ঘ্য [1,2 000 000]এবং প্রোগ্রামটি 0.15 সেকেন্ডের মধ্যে চলতে হবে।

আমি জানি যে কেএমপি এবং রবিন-কার্প সমস্যার উপর 100% স্কোর অর্জনের জন্য যথেষ্ট তবে আমি বায়ার-মুরকে চেষ্টা করে বাস্তবায়ন করতে চেয়েছিলাম। এই ধরণের প্যাটার্ন অনুসন্ধানের জন্য সবচেয়ে ভাল হবে?


6
আপনি যখন নিজের পছন্দের ভাষায় এটি পরীক্ষা করে দেখেন তবে কী খুঁজে পেয়েছেন?
ওয়াল্টার

4
কিছু পরীক্ষায় বায়ার-মুরের অন্যান্য কেএমপিতে ভাল ছিল, তবে আমি সেগুলি "সেরা" বাস্তবায়ন করি তা নিশ্চিত নই। পছন্দের ভাষার ক্ষেত্রে এটি ট্যাগগুলিতে রয়েছে: সি ++ (আপনি নিশ্চিত যে এটি "পছন্দের ভাষা" লিখেছেন তা নিশ্চিত নয়)) পিএস আমিও নিশ্চিত নই যে আমি সেরা পরীক্ষাগুলিতে পরীক্ষা করেছি কিনা।
ভ্যানডামন তাইগি


নথ-মরিস-প্র্যাট যার ও (মি + 2 * এন) রয়েছে ... আপনার অর্থ ও (এম + এন)।
জুলাই

একটি শালীন অ্যালগরিদমিক জটিলতার সাথে একটি বাছুন এবং তারপরে একটি প্রোফাইলার হাতে রেখে মাইক্রো-টিউনটি থেকে এটিকে ছুঁড়ে ফেলা - সর্বদা আমার জন্য কাজ করে। :-D

উত্তর:


38

এটি নির্ভর করে আপনি কী ধরনের অনুসন্ধান করতে চান। প্রতিটি অ্যালগরিদম নির্দিষ্ট কিছু অনুসন্ধানের জন্য বিশেষত ভাল সম্পাদন করে তবে আপনি নিজের অনুসন্ধানের প্রসঙ্গটি বর্ণনা করেন নি।

এখানে অনুসন্ধানের ধরণের কয়েকটি আদর্শ চিন্তাভাবনা রয়েছে:

  • বায়ার-মুর: প্যাটার্নটি প্রাক-বিশ্লেষণ করে ডান থেকে বামে তুলনা করে কাজ করে। যদি কোনও অমিল দেখা দেয় তবে প্রাথমিক বিশ্লেষণটি পাঠ্যটি কতটা সরিয়ে নেওয়া যায় তা নির্ধারণ করতে ব্যবহৃত হয় wr এটি দীর্ঘ অনুসন্ধান নিদর্শনগুলির জন্য বিশেষত ভাল কাজ করে। বিশেষত, এটি উপ-লিনিয়ার হতে পারে, কারণ আপনার পাঠ্যের প্রতিটি অক্ষর পড়ার দরকার নেই।

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

  • আহো-করাসিক: প্রচুর প্রিপ্রোসেসিংয়ের প্রয়োজন, তবে এটি বেশ কয়েকটি নিদর্শনগুলির জন্য করে। আপনি যদি জানেন যে আপনি বার বার একই অনুসন্ধান নিদর্শনগুলি সন্ধান করবেন, তবে এটি অন্যটির চেয়ে অনেক ভাল, কারণ আপনাকে অনুসন্ধান প্রতি একবার নয়, একবারে নিদর্শন বিশ্লেষণ করতে হবে।

সুতরাং, সিএস হিসাবে যথারীতি সামগ্রিক সেরাটির কোনও নির্দিষ্ট উত্তর নেই । এটি বরং কাজের জন্য সঠিক সরঞ্জামটি বেছে নেওয়ার বিষয় is

আপনার নিকৃষ্টতম মামলার যুক্তির জন্য আরেকটি নোট: সেই নিকৃষ্টতম পরিস্থিতি তৈরি করতে প্রয়োজনীয় ধরণের অনুসন্ধানগুলি বিবেচনা করুন এবং এগুলি আপনার ক্ষেত্রে সত্যিই প্রাসঙ্গিক কিনা তা নিয়ে পুরোপুরি চিন্তাভাবনা করুন। উদাহরণস্বরূপ, O(mn)বুইয়ার মুর আলগোরিদিম খারাপ-কেস জটিলতা একটি সার্চ প্যাটার্ন এবং একটি টেক্সট থেকে ডালপালা প্রতিটি ব্যবহারের জন্য শুধুমাত্র একটি অক্ষর (খোঁজার মত aaaমধ্যে aaaaaaaaaaaaaaaaaaaaa) - আপনি কি সত্যিই যে ভালো অনুসন্ধানের জন্য দ্রুত করতে হবে?


আমার কাছে সম্পূর্ণ ইংরেজী বর্ণমালা বা ততোধিক ব্যবহার রয়েছে এবং আমি প্রশ্নটি আপডেট করেছি, ভিক্ষাবৃত্তির সাথে এটি শুরু না করার জন্য দুঃখিত।
ভ্যানডামন তাইগি

এবং হ্যাঁ আমি এমনকি যে ভালো অনুসন্ধানের জন্য দ্রুত করতে হবে
vandamon taigi

1

যদিও এই প্রশ্নের উত্তর দিতে আমি কিছুটা দেরি করেছি, তবে আমি মনে করি Z-Algorithmএটির কোনও অংশগুলির তুলনায় অনেক দ্রুত। এর নিকৃষ্টতম জটিলতা হ'ল ও (এম + এন) এবং এর জন্য প্যাটার্ন / পাঠ্যের কোনও প্রাকপ্রসেসিং প্রয়োজন নেই। অন্যান্য অ্যালগরিদমের তুলনায় কোড করাও খুব সহজ।

এটি নিম্নলিখিত পদ্ধতিতে কাজ করে।

উদাহরণস্বরূপ, একটি স্ট্রিং আছে S ='abaaba'। আমরা z(i)মান খুঁজে পেতে হয় i=0 to len(S)-1। ব্যাখ্যায় যাওয়ার আগে প্রথমে কিছু সংজ্ঞা দেওয়া যাক।

z(i)= না এর উপসর্গের অক্ষরের অক্ষরের সাথে উপসর্গ Sমেলে s(i)

s(i)= ithএর প্রত্যয় S

নিম্নলিখিত জন্য s(i)মান হয় s = 'abaaba'

s(0) = 'abaaba' = S
s(1) = 'baaba'
s(2) = 'aaba'
s(3) = 'aba'
s(4) = 'ba'
s(5) = 'a'

Z মান যথাক্রমে হয়

z(0) = 6 = length(S)
z(1) = 0
z(2) = 1
z(3) = 3
z(4) = 0
z(5) = 1

অ্যালগরিদমের বিস্তারিত বোঝার জন্য নীচের লিঙ্কগুলিকে দেখুন।

http://codeforces.com/blog/entry/3107

https://www.youtube.com/watch?v=MFK0WYeVEag

এখন zকোনও প্রাক প্রসেসিং ওভারহেড ছাড়াই সমস্ত মান খুঁজে পেতে ও (এন) লাগে । এখন একজন ভাবছেন যে আপনি একটি যুক্ত স্ট্রিংয়ের প্যাটার্নটি মেলে এই যুক্তিটি কীভাবে ব্যবহার করতে পারেন?

একটি উদাহরণ দিয়ে দেখা যাক। প্যাটার্ন (পি): aba, পাঠ্য (টি): aacbabcabaad

এটি পি $ টি আকারে রাখুন। ( $- এমন কোনও চরিত্র যা প্যাটার্ন বা পাঠ্য উভয় ক্ষেত্রেই উপস্থিত হয় না I'll আমি $কিছুক্ষণের মধ্যে গুরুত্বের সাথে উপস্থিত হব ))

P$T = aba$aacbabcabaad

আমরা জানি len(P)= 3।

সমস্ত z মান P$Tহয়

z(0) = 16 = len(P$T)
z(1) = 0
z(2) = 1
z(3) = 0
z(4) = 1
z(5) = 1
z(6) = 0
z(7) = 0
z(8) = 2
z(9) = 0
z(10) = 0
z(11) = 3
z(12) = 0
z(13) = 1
Z(14) = 1
Z(15) = 0

এখন যা z(i)= len(P)Ans = 11.সুতরাং আমাদের নিদর্শন উপস্থিত Ans-len(P)-1= 7। চরিত্রের -1জন্য $

এখন কেন $বা এরকম কোনও বিশেষ চরিত্র গুরুত্বপূর্ণ। বিবেচনা করুন P = 'aaa'এবং T = 'aaaaaaa'। বিশেষ অক্ষর ব্যতীত সকলের z(i)ইনক্রিমেন্টাল মান থাকবে। নীচের সূত্রগুলির সাহায্যে পাঠ্য বিন্যাসের অবস্থানটি এখনও খুঁজে পেতে পারে:

কন্ডিশন: z(i)> = len(P)এবং অবস্থান: Ans-len(P)। তবে এই ক্ষেত্রে শর্তটি কিছুটা জটিল এবং বিভ্রান্তিকর হয়ে ওঠে। আমি ব্যক্তিগতভাবে বিশেষ চরিত্রের কৌশলটি ব্যবহার করতে পছন্দ করি।


1
আপনি এখানে নিজেকে ব্যাখ্যা করতে পারেন? বাহ্যিক সাইটগুলির সাথে লিঙ্কগুলি বিশদভাবে ব্যবহৃত হতে পারে, তবে একটি উত্তরের মূলটি অন্য কোনও সাইটের লিঙ্ক অনুসরণ না করে উত্তরে থাকা উচিত।

জেড-অ্যালগরিদম মূলত কেএমপি-র মতো। আমি সন্দেহ এটি অনেক দ্রুত।
টমাস আহলে

2
আমি @ থমাসএহলে এর সাথে একমত কম্পিউটিং z হয় preprocessing। যদিও এটি একটি ভাল ব্যাখ্যা। আমি O(n)এই উত্তরের কারণে কেএমপি প্রি-প্রসেসিং থেকে জেড প্রাক প্রসেসিংয়ে রূপান্তর করার একটি উপায় রেখেছি । এখানে
leewz

-1

ভার্চুয়াল অ্যাড্রেসিং (অক্ষরগুলিতে চিঠিপত্র নির্দেশক) আকারে সফ্টওয়্যারটিতে প্রয়োগ করা বিষয়বস্তু সম্বোধনযোগ্য মেমরি ব্যবহার করুন ।

এটি গড় স্ট্রিং মেলানো অ্যালগরিদমের কাছে অতিমাত্রায়

সিএএম প্রায় 128-অক্ষরের নিদর্শন পর্যন্ত একযোগে এক বিশাল সংখ্যক নিদর্শনগুলির সাথে মেলে (যদি তারা ASCII হয়; যদি তারা কেবল ইউনিকোড হয় তবে)) আপনি যে স্ট্রিংয়ের সাথে মেলে যেতে চান তাতে চিঠির দৈর্ঘ্যের জন্য একটি কল এবং সর্বাধিক প্যাটার্ন দৈর্ঘ্যের দৈর্ঘ্যে প্রতি মেমরি থেকে একটি এলোমেলো পড়া হয়। সুতরাং আপনি যদি একসাথে 90,000,000 অবধি এক 100,000 অক্ষরের স্ট্রিং বিশ্লেষণ করছিলেন (যা বড় আকারের একটি গণনা সংরক্ষণ করতে প্রায় 128 জিআইবি লাগবে), এটি র্যাম থেকে 12,800,000 এলোমেলোভাবে পড়বে, সুতরাং এটি 1 মিমিতে ঘটবে।

ভার্চুয়াল অ্যাড্রেসিং কীভাবে কাজ করে তা এখানে।

যদি আমি 256 স্টার্টফ ঠিকানা দিয়ে শুরু করি, যা প্রথম অক্ষরের প্রতিনিধিত্ব করে, এই অক্ষরগুলি পরবর্তী অক্ষরের 256 এ নির্দেশ করে। যদি কোনও প্যাটার্ন উপস্থিত থাকে না, আপনি এটি সঞ্চয় করবেন না store

সুতরাং আমি যদি অক্ষরগুলির সাথে অক্ষরগুলি লিঙ্ক করে রাখি তবে এটি ভার্চুয়াল ঠিকানার দিকে নির্দেশ করে ভার্চুয়াল ঠিকানার 128 টি স্লাইস রাখার মতো।

এটি কার্যকর হবে - তবে একই সাথে মিলিয়ে 900,000,000 নিদর্শনগুলি পেতে এটিতে যুক্ত করার একটি শেষ কৌশল রয়েছে - এবং আপনি এই চিঠি বাফারগুলিকে পুনরায় ব্যবহারের মাধ্যমে শুরু করার সুযোগটি গ্রহণ করছেন, তবে পরে এটি ছড়িয়ে যায়। আপনি যদি সমস্ত 256 টি অক্ষর বরাদ্দের পরিবর্তে বিষয়বস্তুগুলি তালিকাভুক্ত করেন তবে এটি খুব কম হয়ে যায় এবং আপনি 100 গুণ সক্ষমতা বৃদ্ধি পাবেন কারণ আপনি অবশেষে কেবলমাত্র প্রতিটি অক্ষর পয়েন্টার বাফারে ব্যবহৃত হয় 1 অক্ষর যা আমি ডাব করেছি ' অব্যাহতি ')।

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


4
@ ম্যাগনাসরোবার্টকার্লওয়ুট যে রাউসার ৮১ এর মতো আপনার গাভাতর রয়েছে তা প্রদত্ত, এটি হয় হ্যাশ কোডের সংঘর্ষের জ্যোতির্বিদ্যার কাকতালীয় ঘটনা বা আপনার একই ইমেল ঠিকানা রয়েছে। আপনি যদি উভয় অ্যাকাউন্টের পিছনে একই ব্যক্তি হন তবে আপনার তাদের সাথে মার্জ করার জন্য "আমাদের সাথে যোগাযোগ করুন" ফর্মটি ব্যবহার করা উচিত যাতে আপনি এই উত্তরের উপর ভিত্তি করে সুনামের জন্য যথাযথ কৃতিত্ব পান।
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.